Producer/consumer
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <thread.h>
#include <synch.h>
#define TRUE 1
#define FALSE 0
static void *producer(void*);
static void *consumer(void*);
static char Buff[BUFSIZ];
static cond_t Buff_cond;
static mutex_t Buff_mutex;
static int DataInBuff = FALSE;
main()
{
(void)mutex_init(&Buff_mutex, USYNC_THREAD, NULL);
(void)cond_init (&Buff_cond, USYNC_THREAD, NULL);
(void)thr_create(NULL, 0, producer, NULL, 0, NULL);
(void)thr_create(NULL, 0, consumer, NULL, 0, NULL);
thr_exit(NULL);
/*NOTREACHED*/
}
/*ARGSUSED*/
static void *producer(void *dummy)
{
(void)mutex_lock(&Buff_mutex);
for(;;){
while(DataInBuff == TRUE)
cond_wait(&Buff_cond, &Buff_mutex);
/* At this point,
* the buffer is empty (contents have been output).
* (Re)fill the buffer.
*/
if(fgets(Buff, sizeof(Buff), stdin) == NULL)
exit(EXIT_SUCCESS);
DataInBuff = TRUE;
cond_signal (&Buff_cond);
}
/*NOTREACHED*/
}
/*ARGSUSED*/
static void *consumer(void *dummy)
{
(void)mutex_lock(&Buff_mutex);
for(;;){
while(DataInBuff == FALSE)
cond_wait(&Buff_cond, &Buff_mutex);
/* At this point,
* the buffer has data to be output
*/
(void)fputs(Buff, stdout);
DataInBuff = FALSE;
cond_signal(&Buff_cond);
}
/*NOTREACHED*/
}
Producer/consumer
The program in
``Producer/consumer''
shows a simple producer/consumer example
implemented using the condition variables facilities of the Threads Library.
-
There are two threads, each running different functions.
One runs producer, the other runs consumer.
-
The item being produced and consumed is data in a common buffer.
-
The producer obtains that data with fgets (see
gets(3S))
and places the data in the common buffer.
-
The consumer reads the data from the buffer.
That data is output with fputs (see
puts(3S))
so that its actions
can be confirmed.
-
The actions of producer and consumer threads are coordinated by the
condition variable facility so that they run in strict alternation.
-
Nothing will be output (consumed) until something is placed in the buffer
(produced).
-
Data in the buffer will not be overwritten until it is output.
-
Note that
this example differs from the pseudo-code shown earlier.
The use of the condition variables are not
bracketed by calls to
mutex_lock(3synch)
and
mutex_unlock(3synch).
-
This curiosity arises because the actions of each of these threads
is organized in a loop.
-
The semantics of
cond_wait(3synch)
guarantee that the named
``mutex'' will be released while a thread is waiting and reacquired
before return from that function.
-
The condition (DataInBuff) is tested (for different values)
by each thread only when the thread holds the ``mutex''
and the use of cond_wait by each threads allows the other
to acquire the ``mutex''.
-
The initial calls to
mutex_lock(3synch)
by each
thread and the initial state of DataInBuff are organized so that:
-
Proper conditions are achieved for the initial pass by each thread.
-
The program will work correctly no matter which thread acquires
the ``mutex'' on the first pass.
-
The producer thread terminates the process with the
exit(2)
system call when it can obtain no more data from fgets
(see
gets(3S)).
Previous topic:
Dining philosophers
© 2004 The SCO Group, Inc. All rights reserved.
UnixWare 7 Release 7.1.4 - 27 April 2004