LinuxQuestions.org
Register a domain and help support LQ
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices

Reply
 
LinkBack Search this Thread
Old 06-01-2012, 09:36 AM   #1
vikasbansal27
LQ Newbie
 
Registered: May 2012
Posts: 25

Rep: Reputation: Disabled
Producer Consumer problem (bounded buffer)


Code:
#include<stdio.h>
#include<pthread.h>
#include<stdlib.h>
#include<buffer.h>
#include<semaphore.h>

sem_t sem;

pthread_mutex_t mutex;

buffer_item buffer[BUFFER_SIZE];/*buffer declaration*/
int H; 
int T; /*intializing head and tails for queue*/
void *producer(void *param);
void *consumer(void *param);

main(int argc, char *argv[])
{
int i,j,s,n_p,n_c,p=0;
s=atoi(argv[1]);  /*sleep time*/
n_p=atoi(argv[2]);/*number of producers*/
n_c=atoi(argv[3]);/*number of consumers*/
H=T=2;
pthread_mutex_init(&mutex, NULL);
sem_init(&sem, 0, 5);
pthread_t tid[n_c+n_p-1];
   
for(i=0;i<n_p;i++)
{
printf("\n%dth producer thread created\n",i);
pthread_create(&tid[p++],NULL, producer, NULL);
printf("\n%dth consumer thread created\n",i);
pthread_create(&tid[p++],NULL, consumer, NULL);

}

/*for(j=0;j<n_c;j++)
{
printf("\n%dth consumer thread created\n",j);
pthread_create(&tid[n_p+j],NULL, consumer, NULL);

}*/

//printf("\ngoing to sleep\n");
sleep(s);
//printf("\nI am awake\n");
for(i=0;i<6;i++)
printf("buffer-->%d ", buffer[i]);
exit(1);
}

void *producer(void *param)
{
float rand1_sleep;
buffer_item rand1;
while(1)
{
	rand1_sleep=rand()%10;
	rand1_sleep=rand1_sleep/100;
        //printf("\nrand1_sleep producer-->%f\n",rand1_sleep);
	sleep(rand1_sleep);
	rand1=rand();
        printf("\nproducer produced %d\n",rand1);
        if(edit_buffer('p',rand1,NULL))
        printf("\nnot inserted\n");
}

}

void *consumer(void *param)
{
float rand_sleep;
buffer_item rand1,*h;
h= (buffer_item *)malloc(sizeof(buffer_item *));
while(1)
{
	rand_sleep=rand()%10;
	rand_sleep=rand_sleep/100;
        //printf("\nrand_sleep consumer-->%f\n",rand_sleep);
	sleep(rand_sleep);
        if(edit_buffer('c',0,h))
        	printf("\nerror in removing\n");
        else
           printf("\nconsumer consumed\n");

}
}

int edit_buffer(char a, buffer_item item, buffer_item *item1 )
{
int H1;
pthread_mutex_lock(&mutex);
   if(a=='p')
	{
		printf("\nproducer locked it\n");	
		
	
		   if(H==T+1)
			{
				printf("error: queue full");
				pthread_mutex_unlock(&mutex);
				printf("\nproducer UNlocked it\n");
				return(-1);
			}
   			else {sem_wait(&sem);
			        H1=H;				
				buffer[T]=item;
				H=H1;
	        		T=(T+1)%6;
                		printf("\nprod: H-->%d  T-->%d\n",H,T);	
				printf("\nproducer UNlocked it\n");
       				pthread_mutex_unlock(&mutex);
				return 0;
				}
        }
   else if(a=='c')
	{
           printf("\nconsumer locked it\n");
		
   			if(H==T)
			{
				printf("error: queue empty");
				printf("\nconsumer UNlocked it\n");
                		pthread_mutex_unlock(&mutex);
				return -1;            
			}
		       else {
				sem_post(&sem);
                               //printf("\nERROR: H==%d\n",H);
				*item1=buffer[H];
                		H=(H+1)%6;
               			 printf("\ncons: H-->%d  T-->%d\n",H,T);
				printf("\nconsumer UNlocked it\n"); 				        pthread_mutex_unlock(&mutex);
				return 0;
        		    }

        }
	
}
 
Old 06-01-2012, 09:41 AM   #2
vikasbansal27
LQ Newbie
 
Registered: May 2012
Posts: 25

Original Poster
Rep: Reputation: Disabled
This is a standard producer consumer problem implemented as stated in book of Galvin in the following order :
1. get command line arguments.
2.Initialize buffer.
3.Create producer threads.
4.create consumer threads.
5.sleep
6.exit

the problem is when the parent thread is going to sleep, no producer or consumer are trying to access the buffer. I am baffled by this..please help me out of this.
 
Old 06-01-2012, 11:09 AM   #3
sundialsvcs
Guru
 
Registered: Feb 2004
Location: SE Tennessee, USA
Distribution: Gentoo, LFS
Posts: 5,042

Rep: Reputation: 952Reputation: 952Reputation: 952Reputation: 952Reputation: 952Reputation: 952Reputation: 952Reputation: 952
Obviously, we're not going to do your homework for you, but perhaps I can help you sort-out the problem.

Producer/Consumer problems involve the use of two mutual-exclusion or signaling devices. A mutex must be used to control the integrity of the data-structure, as is the case with all shared structures: you must be holding the mutex before you can examine or touch the structure. But, in addition, you need a second mechanism to deal with the situation where the queue is full. The producer, upon deducing that there is nowhere to put the value, must sleep ... without deadlocking the consumer. The consumer must signal the producer if the queue had been full and no longer is ... without the producer falling into a sleeps-forever if it happens to be "going to sleep" a millisecond after the wakeup call is fired by the consumer.

You need to study this problem, solve it for yourself, study all that has been written about it. Solve it for yourself. You need to study this problem.
 
1 members found this post helpful.
Old 06-01-2012, 12:32 PM   #4
vikasbansal27
LQ Newbie
 
Registered: May 2012
Posts: 25

Original Poster
Rep: Reputation: Disabled
sleep is provided in parent thread to let producer and consumer threads so some activities in the program. but maximum times when ever parent thread goes to sleep nothing happens...no producer or consumer tries to access the critical section. I am pasting here the logs of what I did...for same input the output were quite different.

[vikas@localhost vikas]$ ./a.out 4 1 3

0th producer thread created

0th consumer thread created

1th consumer thread created

2th consumer thread created

going to sleep---------------------------------------------------------------------------------->>> here something is happening after parent thread goes to sleep.

producer produced 1957747793

producer locked it

prod: H-->2 T-->3

producer UNlocked it

producer produced 719885386

producer locked it

prod: H-->2 T-->4

producer UNlocked it

consumer locked it

cons: H-->3 T-->4

consumer UNlocked it

consumer consumed

consumer locked it

cons: H-->4 T-->4

consumer UNlocked it

consumer consumed

I am awake------------------------------------------------------------------------------------->>>>parent thread sleep ends
buffer-->0 buffer-->0 buffer-->1957747793 buffer-->719885386 buffer-->0 buffer-->4



***********************************second case---same input**********************************


[vikas@localhost vikas]$ ./a.out 4 1 3

0th producer thread created

producer produced 846930886

producer locked it

prod: H-->2 T-->3

producer UNlocked it

0th consumer thread created

consumer locked it

cons: H-->3 T-->3

consumer UNlocked it

consumer consumed

1th consumer thread created

2th consumer thread created

going to sleep------------------------------------------------------------------>>> nothing
happens btw
I am awake----------------------------------------------------------------------->>>these two.
buffer-->0 buffer-->0 buffer-->846930886 buffer-->0 buffer-->0 buffer-->3



I know that there are some rand functions involved which can change the output but still if the parent is sleeping for 4 seconds...its enough time for producers and consumers to have a go.
 
Old 06-01-2012, 07:24 PM   #5
Nominal Animal
Senior Member
 
Registered: Dec 2010
Location: Finland
Distribution: Xubuntu, CentOS, LFS
Posts: 1,723
Blog Entries: 3

Rep: Reputation: 942Reputation: 942Reputation: 942Reputation: 942Reputation: 942Reputation: 942Reputation: 942Reputation: 942
Quote:
Originally Posted by sundialsvcs View Post
You need to study this problem, solve it for yourself, study all that has been written about it. Solve it for yourself. You need to study this problem.
Very well put. The problem is not really that complex.

Quote:
Originally Posted by sundialsvcs View Post
Producer/Consumer problems involve the use of two mutual-exclusion or signaling devices. A mutex must be used to control the integrity of the data-structure,
Well, one can use two semaphores (assuming the semaphore has more states than the queue has elements), or atomic counters, so a mutex is not strictly required.

My favorite variant of the problem involves a singly-linked list, and either one producer and multiple consumers, or multiple producers and one consumer, handled locklessly (using compare-and-swap, requiring nonstandard built-ins). Since there is no bound to the queue size, producers never wait. Since a producer always knows if it added an item to an empty list, they can also post a semaphore (or signal a condition variable protected by a mutex) to wake up a waiting consumer.

The real-world case usually involves two such structures: one with empty list items, and one with used items. (The producers are then consumers of the empty items.) That way the queue is naturally synchronized and limited in size, but easily growable/shrinkable when needed. If instead of waiting on an empty list you switch the role (consumer/producer) of a thread, you get a dynamically balancing system, with surprisingly small amount of code. I personally like the robustness of it.

Quote:
Originally Posted by sundialsvcs View Post
The consumer must signal the producer if the queue had been full and no longer is ... without the producer falling into a sleeps-forever if it happens to be "going to sleep" a millisecond after the wakeup call is fired by the consumer.
Exactly. This is why using a semaphore for this second purpose is not recommended.

vikasbansal27, pthreads has a condition variable type, pthread_cond_t, and associated functions pthread_cond_wait() and pthread_cond_signal(), which are designed for exactly this purpose.

When you hold a mutex, but have to wait, you can wait on a condition variable. When you wait on a condition variable, you must hold some mutex. The mutex is unlocked and the thread will wait for a signal or a broadcast on the condition variable atomically: there is no possibility of a signal slipping by. When someone signals (waking up one) or broadcasts (waking up all) on the condition variable, (each of) the woken up thread(s) will automatically atomically re-acquire the lock before it returns from the condition variable wait call.

Let me reiterate: during this, the thread will be holding the mutex, waiting on the condition variable with mutex unlocked, waiting to lock the mutex, or holding the mutex, without any gaps in between. There is no danger of missing a signal or a broadcast.

Furthermore, it is perfectly okay to signal on a condition variable without any threads waiting on it: nothing will happen then. Unlike semaphores, the condition variable itself has no state; if there are no waiters, a signal or broadcast just vanishes, it is not recorded in the condition variable. A wait on a condition variable does not depend on any previous signals or broadcasts done on it; it will always wait until the next one.

Usually, each condition variable is associated with one mutex. The mutex can be locked by any time regardless of the condition variable. (It must always be unlocked by that same thread, either explicitly, or by waiting on a condition variable and specifying that locked mutex.) The condition variable can be signaled or broadcast by any thread at any time; no need to hold the mutex at the same time. If a thread does hold the mutex while signaling on the condition variable, the woken up thread will continue only after the mutex is unlocked first.

There is also a pthread_cond_timedwait() function, which works just like pthread_cond_wait(), except that you also set a wall clock time at which point the thread will wake up just as if the condition variable had been signaled or broadcast on. (There may be a small delay in waking up, since the thread will re-acquire the mutex before it returns from the call even if timeout occurs.)

Last edited by Nominal Animal; 06-01-2012 at 07:37 PM.
 
1 members found this post helpful.
Old 06-02-2012, 04:00 AM   #6
vikasbansal27
LQ Newbie
 
Registered: May 2012
Posts: 25

Original Poster
Rep: Reputation: Disabled
Thank you 'sundialsvcs' and 'Nominal Animal' for you replies.
I the point which you two are trying to make. I am using Sem_wait after acquiring the mutex lock which may result in deadlock condition. But If I change the order i.e use Sem_wait before the mutex lock, I can make the threads wait before they acquire any lock. Suppose buffer is full and producer is trying to access the critical section, it will be waiting on sem_wait(empty). Now consumer can acquire the lock and give a sem_post(empty) so that producer can produce again. If I am going in the right direction, then will there be any need for conditional variable now?
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off
Trackbacks are Off
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Fast Producer, Slow Consumer eviatarkhen Linux - Software 1 03-08-2012 11:57 AM
Producer and Consumer problem teesha Linux - Kernel 1 02-26-2012 11:58 PM
How to implement a POSIX threaded program to solve producer/consumer problem cy163 Programming 3 09-13-2008 09:38 AM
The old producer-consumer problem still a problem for me!!!!!!!!!!!!! skie_knite007 Programming 1 12-14-2005 07:39 PM


All times are GMT -5. The time now is 12:09 AM.

Main Menu
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
identi.ca: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration