This is my current code for the Producer-Consumer problem. I compiled it and ran it but nothing is printed. The command line takes in 3 arguments: Sleep time, producer threads, consumer threads. I've tried setting the values as 5, 1, 1 respectively, the sleep timer works but I'm unsure about the rest.
Code for buffer.h:
typedef int buffer_item;
#define BUFFER_SIZE 5
Code for buffer.c:
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <semaphore.h>
#include "buffer.h"
buffer_item buffer[BUFFER_SIZE];
void *producer(void *param);
void *consumer(void *param);
pthread_mutex_t mutex;
sem_t empty;
sem_t full;
int insert_item(buffer_item item)
{
do
{
wait(empty);
wait(mutex);
signal(mutex);
signal(full);
}while(1);
return 0;
}
int remove_item(buffer_item *item)
{
do
{
wait(full);
wait(mutex);
signal(mutex);
signal(empty);
}while(1);
return 0;
}
int main(int argc, char *argv[])
{
int sleepTime;
int producerThreads;
int consumerThreads;
int counter_1;
int counter_2;
if(argc != 4)
{
return -1;
}
sleepTime = atoi(argv[1]);
producerThreads = atoi(argv[2]);
consumerThreads = atoi(argv[3]);
srand((unsigned)time(NULL));
for(counter_1 = 0; counter_1 < producerThreads; counter_1++)
{
pthread_t tid;
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_create(&tid, &attr, producer, NULL);
}
for(counter_2 = 0; counter_2 < consumerThreads; counter_2++)
{
pthread_t tid;
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_create(&tid, &attr, consumer, NULL);
}
sleep(sleepTime);
return 0;
}
void *producer(void *param)
{
buffer_item item;
int randomTime;
int counter_1 = 0;
while(1)
{
randomTime = rand() % 1000 + 1;
sleep(randomTime);
item = rand();
if(insert_item(item))
{
fprintf(stderr, "Error.");
}
else
{
printf("Producer ID: %lu, Produced Item: %d\n", pthread_self(), item);
printf("The buffer now contains %d items\n", counter_1);
++counter_1;
}
}
}
void *consumer(void *param)
{
buffer_item item;
int randomTime;
int counter_2 = 0;
while(1)
{
randomTime = rand() % 1000 + 1;
sleep(randomTime);
if(insert_item(item))
{
fprintf(stderr, "Error.");
}
else
{
printf("Consumer ID: %lu, Consumed Item: %d\n", pthread_self(), item);
printf("The buffer now contains %d items\n", counter_2);
++counter_2;
}
}
}
So far I've tried declaring the tid separately, skipping sleep and join the threads, but it still doesn't print.
Your code can't possibly run, indeed it doesn't even compile.
Here's a list of issues that need to be addressed:
wait should be sem_wait
signal should be sem_post for semaphores
int sem_wait(sem_t *sem); and int sem_post(sem_t *sem); take the pointer to a semaphore
sem_wait(mutex) and sem_post(mutex) give something like "incompatible type for argument 1 of sem_wait", I guess you want to acquire and release the lock on the mutex like pthread_mutex_lock(&mutex) and pthread_mutex_unlock(&mutex)
in the consumer if(insert_item(item)): item is used uninitialized
still in the consumer you use insert_item instead of remove_item
Coming to the main question "I compiled it and ran it but nothing is printed", it doesn't print anything because producer and consumer call, respectively, insert_item and remove_item and are trapped inside infinite loops (e.g. while(1))
Related
Hi I am trying to implement an solution to producer consumer problem with threads and semaphores.
I have the two functions that the threads consumer and producer will call but they aren't executing. I am not sure what I am doing wrong as I am not getting any errors, my program is just not executing the thread functions. I am creating and joining the thread, I am not sure what is causing the issue
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <semaphore.h>
#include <stdlib.h>
#include <errno.h>
#include "buffer.h"
struct bufferStruct *item; //calls buffer structure from buffer.h
pthread_mutex_t mutex; //lock for synchronizing execution of threads(producer and consumer)
sem_t empty; //indicates buffer is empty
sem_t full; //indicates buffer is full
int input = 0;
int newitem;
pthread_attr_t attr;
void *producer(void *param)
{
for(int i = 0; i < 5; i++)
{
sem_wait(&empty);
pthread_mutex_lock(&mutex);
newitem = rand();
item->content[item->in] = newitem;
printf("Producer prouced item %d at position %d in buffer\n", newitem, item->in);
item->in = (item->in+1) % MAX_SIZE;
pthread_mutex_unlock(&mutex);
sem_post(&full);
sleep(1);
}
}
void *consumer(void * param)
{
for(int i =0; i< 5; i++)
{
sem_wait(&full);
pthread_mutex_lock(&mutex);
newitem = item->content[item->out];
printf("Consumer has consumed item %d at position %d in buffer\n", newitem, item->out);
item->out = (item->out+1) % MAX_SIZE;
pthread_mutex_unlock(&mutex);
sem_post(&empty);
sleep(1);
}
}
int main()
{
int initval = 1;
int initval2 = 2;
sem_init(&full, 1, 0);
sem_init(&empty, 1, MAX_SIZE);
if(pthread_mutex_init(&mutex,NULL)!=0){
printf("Mutex init failed\n");
return 1;
}
pthread_attr_init(&attr);
pthread_t thread_produce, thread_consume;
printf("Starting threads...\n");
pthread_create(&thread_produce, &attr, producer, (void*)&(initval));
pthread_create(&thread_consume, &attr, consumer, (void*)&(initval2));
pthread_join(thread_produce, NULL);
pthread_join(thread_consume, NULL);
printf("Threads done executing...\n");
pthread_mutex_destroy(&mutex);
sem_destroy(&empty);
sem_destroy(&full);
exit(0);
}
You declare
struct bufferStruct *item;
then you use item without ever assigning it to point to anything. Undefined behavior results.
If I fix that (first synthesizing a version struct bufferStruct and choosing a MAX_SIZE) then the program compiles without error and seems to run successfully.
I'm having an issue with my sleep cycles in the ProducerConsumer.h file. If I comment out the sleep(rnum) the program will access the line printf("producer produced %d\n", item); If it's not commented out it will never access that line and I cant figure out why.
Here is my code it's in 3 separate files I would be grateful of any help thank you.
buffer.h:
typedef int buffer_item;
#define BUFFER_SIZE 5
int insert_item(buffer_item item);
int remove_item(buffer_item *item);
ProducerConsumer.h:
#include <stdlib.h> /* required for rand() */
#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>
#include <iostream>
#include "buffer.h"
#define RAND_DIVISOR 100000000;
#define TRUE 1
int counter;
buffer_item buffer[BUFFER_SIZE];
pthread_mutex_t mutex;
sem_t full, empty;
/* Producer Thread */
void *producer(void *param) {
buffer_item item;
while(TRUE) {
/* sleep for a random period of time */
int rNum = rand() / RAND_DIVISOR;
sleep(rNum);
printf("producer produced %d\n", item);
/* generate a random number */
item = rand();
/* acquire the empty lock */
sem_wait(&empty);
/* acquire the mutex lock */
pthread_mutex_lock(&mutex);
if(insert_item(item)) {
fprintf(stderr, " Producer report error condition\n");
} else {
printf("producer produced %d\n", item);
}
/* release the mutex lock */
pthread_mutex_unlock(&mutex);
/* signal full */
sem_post(&full);
}
}
/* Consumer Thread */
void *consumer(void *param) {
buffer_item item;
while(TRUE) {
/* sleep for a random period of time */
int rNum = rand() / RAND_DIVISOR;
sleep(rNum);
/* aquire the full lock */
sem_wait(&full);
/* aquire the mutex lock */
pthread_mutex_lock(&mutex);
if(remove_item(&item)) {
fprintf(stderr, "Consumer report error condition\n");
} else {
printf("consumer consumed %d\n", item);`enter code here`
}
/* release the mutex lock */
pthread_mutex_unlock(&mutex);
/* signal empty */
sem_post(&empty);
}
}
int insert_item(buffer_item item) {
if(counter < BUFFER_SIZE) {
buffer[counter] = item;
counter++;
return 0;
} else {
return -1;
}
}
int remove_item(buffer_item *item) {
if(counter > 0) {
*item = buffer[(counter-1)];
counter--;
return 0;
} else {
return -1;
}
}
main.cpp:
#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>
#include <unistd.h>
#include "ProducerConsumer.h"
#include "buffer.h"
pthread_t tid;
pthread_attr_t attr;
void initializeData()
{
pthread_mutex_init(&mutex, NULL);
sem_init(&full, 0, 0);
sem_init(&empty, 0, BUFFER_SIZE);
pthread_attr_init(&attr);
counter = 0;
}
int main() {
int i;
int numProd = 5; /* Number of producer threads */
int numCons = 5; /* Number of consumer threads */
initializeData();
/* Create the producer threads */
for(i = 0; i < numProd; i++) {
/* Create the thread */
pthread_create(&tid,&attr,producer,NULL);
}
/* Create the consumer threads */
for(i = 0; i < numCons; i++) {
/* Create the thread */
pthread_create(&tid,&attr,consumer,NULL);
}
void *producer(void *param);
void *consumer(void *param);
/* Exit the program */
printf("Exit the program\n");
exit(0);
}
The RAND_MAX value is likely at least 32767, causing the the following line:
int rNum = rand() / RAND_DIVISOR;// defined as 100000000
to most always set rNum == 0.
Change statement to get a non-zero value:
int rNum = 1 + rand() % 10;// yields 1-10
Also, call srand() one time, and before using rand(). eg:
void *producer(void *param) {
buffer_item item;
srand((unsigned) time(&t));
...
I need to write a program for class that creates 8 threads. 4 producer, and 4 consumer. The producers need to loop, and randomly send SIGUSR1 or SIGUSR2 to all consumer threads. Only 2 should register if they have received SIGUSR1 and the other 2 register SIGUSR2.
When I try to run it all threads are created, "prod ready" is printed by all 4 producer threads,"waiting 1" is printed by both threads, but "waiting 2" is printed 3 times then all threads exit. At the end of debugging it says that the process exits normally.
I need to use semaphores to control the critical regions. Any help would be great.
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <semaphore.h>
#include <signal.h>
#define NP 4
#define NC1 2
#define NC2 2
#define CNT 10
void handler1(int signum);
void handler2(int signum);
typedef struct {
int sent;
int received;
int buf[1];
int SIG1;
int SIG2;
sem_t con;
sem_t prod;
} sbuf_t;
sbuf_t buff;
void *producer() {
printf("prod ready \n");
int s;
while(1){
sem_wait(&buff.prod);
s=rand()%2;
if(s==1){
buff.sent++;
kill(0,SIGUSR1);
}
else if(s==2){
buff.sent++;
kill(0,SIGUSR2);
}sem_post(&buff.prod);
}
}
void *consumer1() {
signal(SIGUSR1, handler1);
printf("waiting 1\n");
while(1){
}
}
void *consumer2() {
signal(SIGUSR2, handler2);
printf("waiting 2\n");
while(1){
}
}
void handler1(int signum){
if(signum==SIGUSR1){
sem_wait(&buff.con);
printf("Caught 1\n");
buff.received++;
buff.SIG1++;
sem_post(&buff.con);
}
}
void handler2(int signum){
if(signum==SIGUSR2){
sem_wait(&buff.con);
printf("caught 2 \n");
buff.received++;
buff.SIG2++;
sem_post(&buff.con);
}
}
void main(){
pthread_t threads[9];
buff.SIG1=0;
buff.SIG2=0;
buff.sent=0;
buff.received=0;
int index;
sem_init(&buff.con, 0, 0);
sem_init(&buff.prod, 0, 0);
for (index = 0; index < NP; index++) {
pthread_create(&threads[index], NULL, producer,NULL);
}
for (index = 0;index < NC1;index++) {
pthread_create(&threads[index+4], NULL, consumer1,NULL);
}
for (index = 0;index < NC2;index++) {
pthread_create(&threads[index+6], NULL, consumer2,NULL);
}
}
In the main() function, the threads are being created,
then main() exits.
When main() exits, all the threads are also exited.
Suggest reading about such functions as: pthread_exit() and pthread_join()
Note: the following has an error in the handling of the signals and in the handling of the semaphores, but will demonstrate the use of pthread_join() and pthread_exit()
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <semaphore.h>
#include <signal.h>
#define NP 4
#define NC1 2
#define NC2 2
#define CNT 10
#define MAX_THREADS (9)
void handler1(int signum);
void handler2(int signum);
struct sbuf_t
{
int sent;
int received;
int buf[1];
int SIG1;
int SIG2;
sem_t con1;
sem_t con2;
sem_t prod;
};
typedef struct sbuf_t myData;
myData buff;
void *producer( void *dummy )
{
(void)dummy;
printf("prod ready \n");
int s;
while(1)
{
sem_wait(&buff.prod);
s=rand()%2;
if( !s )
{
buff.sent++;
kill( 0, SIGUSR1 );
}
else // if( s )
{
buff.sent++;
kill( 0, SIGUSR2 );
}
//sem_post(&buff.prod);
}
pthread_exit( NULL );
} // end thread: producer
void *consumer1( void *dummy )
{
(void)dummy;
//signal(SIGUSR1, handler1);
printf("waiting 1\n");
while(1)
{
sem_wait( &buff.con1 );
// do something
//sem_post( &buff.prod );
}
pthread_exit( NULL );
} // end thread: consumer1
void *consumer2( void *dummy )
{
(void)dummy;
//signal(SIGUSR2, handler2);
printf("waiting 2\n");
while(1)
{
sem_wait( &buff.con2 );
// do something
//sem_post( &buff.prod );
}
pthread_exit( NULL );
} // end thread: consumer2
void handler(int signum)
{
sem_post(&buff.prod);
if(signum==SIGUSR1)
{
//sem_wait(&buff.con);
puts("Caught 1");
buff.received++;
buff.SIG1++;
sem_post(&buff.con1);
}
else if(signum==SIGUSR2)
{
//sem_wait(&buff.con);
puts("caught 2");
buff.received++;
buff.SIG2++;
sem_post(&buff.con2);
}
} // end signal handler: handler2
int main( void )
{
pthread_t threads[ MAX_THREADS ];
buff.SIG1=0;
buff.SIG2=0;
buff.sent=0;
buff.received=0;
int index;
sem_init(&buff.con1, 0, 0);
sem_init(&buff.con2, 0, 0);
sem_init(&buff.prod, 0, 0);
signal(SIGUSR2, handler);
signal(SIGUSR1, handler);
for (index = 0; index < NP; index++)
{
pthread_create(&threads[index], NULL, producer,NULL);
}
for (index = 0;index < NC1;index++)
{
pthread_create(&threads[index+4], NULL, consumer1,NULL);
}
for (index = 0;index < NC2;index++)
{
pthread_create(&threads[index+6], NULL, consumer2,NULL);
}
for( size_t x=0; x<MAX_THREADS; x++ )
{
pthread_join( threads[x], NULL );
}
} // end function: main
HOWEVER, the methods to handle signals to threads does not use kill() as that is for processes.
rather the code should use functions similar to::
int pthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex);
int pthread_cond_signal(pthread_cond_t *cond)
The signaled thread should block on a pthread_cond_wait() call until another thread sends a signal using pthread_cond_signal(), with the same condition variable.
Considering the analogy with signals delivered to processes, this is a bit different because the signaled thread has already suspended its execution waiting for a signal, unlike a process that simply gets interrupted and goes on.
For you example, you are creating your producers before your consumers. Also in your producer, you are using a random number generator to determine if you issue USR1 or USR2. Your description gave the impression you wanted two of each (versus some random mix totaling 4) which is what I see the code doing for you.
Trying to compile my code in linux by doing gcc -o consumer.c -lpthread -lm and I am getting compile errors about having undeclared for things I, to the best of my knowledge, have declared. Most of the undeclared seem to be related to buffers, of which this is my first program using buffers. Here are the errors (edited to reflect changes)
typedef char buffer_item buffer[BUFFER_SIZE]; // asm or __attribute__ before "buffer"
both of these(expected ')' before 'item'
int insert_item(buffer_item item)
int insert_item(buffer_item item)
int remove_item(buffer_item *item) //expected ')' before * token
and here is my full code after the changes
#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>
#define RAND_DIVISOR 100000000
#define TRUE 1
#define BUFFER_SIZE 1000
pthread_mutex_t mutex; //mutex lock
sem_t full, empty; //semaphores
typedef char buffer_item buffer[BUFFER_SIZE];
int counter; //buffer counter
pthread_t tid1, tid2; //Thread ID
pthread_attr_t attr; // thread attributes
void *producer(void *param); // producer thread
void *consumer(void *param); //consumer thread
void initializeData() {
pthread_mutex_init(&mutex, NULL); //Create mutex lock
sem_init(&full, 0, 0); // Create the full semaphore and initialize to 0
sem_init(&empty, 0, BUFFER_SIZE); // Create the empty semaphore and initialize to BUFFER_SIZE
pthread_attr_init(&attr); //default attributes
counter = 0;
}
// Producer Thread
int insert_item(buffer_item item)
void *producer(void *param) {
while(TRUE) {
// random sleep time
int rNum = rand() / RAND_DIVISOR;
sleep(rNum);
int item = rand()%100; // item is a random number between 1-100
sem_wait(&empty); //get empty lock
pthread_mutex_lock(&mutex); //get mutex lock
if(insert_item(item)) {
fprintf(stderr, " Producer report error condition\n");
}
else {
printf("producer produced %d\n", item);
}
pthread_mutex_unlock(&mutex); //release mutex lock
sem_post(&full); //signal full
}
}
// Consumer Thread
void *consumer(void *param) {
while(TRUE) {
int rNum = rand() / RAND_DIVISOR; // sleep for a random period of time
sleep(rNum);
int item = rand()%100; // item is a random number between 1-100
sem_wait(&full);// aquire the full lock */
pthread_mutex_lock(&mutex);// aquire the mutex lock
if(remove_item(&item)) {
fprintf(stderr, "Consumer report error condition\n");
}
else {
printf("consumer consumed %d\n", item);
}
pthread_mutex_unlock(&mutex);// release mutex lock
sem_post(&empty); //signal empty
}
}
int insert_item(buffer_item item)
{
// add item as long as buffer isn't full
if(counter < BUFFER_SIZE) {
buffer[counter] = item;
counter++;
return 0;
}
else {
return -1; //buffer full error
}
}
// Remove an item from the buffer
int remove_item(buffer_item *item)// remove item and decrement counter when buffer not empty
{
if(counter > 0) {
*item = buffer[(counter-1)];
counter--;
return 0;
}
else { //buffer empty error
}
return -1;
}
int main(int argc, char *argv[]) {
int i; //loop counter
if(argc != 4) {
fprintf(stderr, "USAGE:./main.out <INT> <INT> <INT>\n");
}
int mainSleepTime = atoi(argv[1]); // sleep time in seconds
int numProd = atoi(argv[2]); // producer threads
int numCons = atoi(argv[3]); // consumer threads
initializeData(); //initialize app
for(i = 0; i < numProd; i++) {
pthread_create(&tid1,&attr,producer,NULL);
}
for(i = 0; i < numCons; i++) {
pthread_create(&tid2,&attr,consumer,NULL);
}
// sleep in milliseconds
//sleep(mainSleepTime);
pthread_join(tid1, NULL);
pthread_join(tid2, NULL);
printf("Program Exiting\n");
exit(0);
}
Edit: latest code and screenshot of errors http://tinypic.com/r/xptzww/9
#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>
#define RAND_DIVISOR 100000000
#define TRUE 1
#define BUFFER_SIZE 1000
pthread_mutex_t mutex; //mutex lock
sem_t full, empty; //semaphores
typedef char buffer_item;
int counter; //buffer counter
pthread_t tid1, tid2; //Thread ID
pthread_attr_t attr; // thread attributes
void *producer(void *param); // producer thread
void *consumer(void *param); //consumer thread
void initializeData() {
pthread_mutex_init(&mutex, NULL); //Create mutex lock
sem_init(&full, 0, 0); // Create the full semaphore and initialize to 0
sem_init(&empty, 0, BUFFER_SIZE); // Create the empty semaphore and initialize to BUFFER_SIZE
pthread_attr_init(&attr); //default attributes
counter = 0;
}
// Producer Thread
int insert_item(buffer_item item)
void *producer(void *param) {
while(TRUE) {
// random sleep time
int rNum = rand() / RAND_DIVISOR;
sleep(rNum);
int item = rand()%100; // item is a random number between 1-100
sem_wait(&empty); //get empty lock
pthread_mutex_lock(&mutex); //get mutex lock
if(insert_item(item)) {
fprintf(stderr, " Producer report error condition\n");
}
else {
printf("producer produced %d\n", item);
}
pthread_mutex_unlock(&mutex); //release mutex lock
sem_post(&full); //signal full
}
}
// Consumer Thread
void *consumer(void *param) {
while(TRUE) {
int rNum = rand() / RAND_DIVISOR; // sleep for a random period of time
sleep(rNum);
int item = rand()%100; // item is a random number between 1-100
sem_wait(&full);// aquire the full lock */
pthread_mutex_lock(&mutex);// aquire the mutex lock
if(remove_item(&item)) {
fprintf(stderr, "Consumer report error condition\n");
}
else {
printf("consumer consumed %d\n", item);
}
pthread_mutex_unlock(&mutex);// release mutex lock
sem_post(&empty); //signal empty
}
}
int insert_item(buffer_item item){// add item as long as buffer isn't full
if(counter < BUFFER_SIZE) {
buffer[counter] = item;
counter++;
return 0;
}
else {
return -1; //buffer full error
}
}
// Remove an item from the buffer
int remove_item(buffer_item *item)// remove item and decrement counter when buffer not empty
{
if(counter > 0) {
*item = buffer[(counter-1)];
counter--;
return 0;
}
else { //buffer empty error
}
return -1;
}
int main(int argc, char *argv[]) {
int i; //loop counter
if(argc != 4) {
fprintf(stderr, "USAGE:./main.out <INT> <INT> <INT>\n");
}
int mainSleepTime = atoi(argv[1]); // sleep time in seconds
int numProd = atoi(argv[2]); // producer threads
int numCons = atoi(argv[3]); // consumer threads
initializeData(); //initialize app
for(i = 0; i < numProd; i++) {
pthread_create(&tid1,&attr,producer,NULL);
}
for(i = 0; i < numCons; i++) {
pthread_create(&tid2,&attr,consumer,NULL);
}
// sleep in milliseconds
//sleep(mainSleepTime);
pthread_join(tid1, NULL);
pthread_join(tid2, NULL);
printf("Program Exiting\n");
exit(0);
}
You have declared but not defined BUFFER_SIZE.
Instead
char BUFFER_SIZE;
try
char BUFFER_SIZE = some_value;
where some_value should be anything between 1-255
Line:
char buffer_item buffer[BUFFER_SIZE];
should be:
char buffer_item[BUFFER_SIZE];
A variable declaration should look like:
<type name> <variable name>;
There is no standard type buffer_item. If you want to use custom type name it can be defined:
typedef char buffer_item;
I assume that you wanted to use char for that type, since item should keep numbers from 0 to 99 and the char type is enough for that.
After that line the name buffer_item is alias for char. So variables can be declared as buffer_item buffer[BUFFER_SIZE]; or buffer_item item;.
In that case lines like char buffer_item; are redundant. Also you do not need to write char before buffer_item, since buffer_item is already another name for char, so char buffer_item; is the same as char char; that does not make any sense.
Probably that the unknow symbol BUFFER_SIZE should defined as you define #define RAND_DIVISOR 100000000. Typically capital letters in names in C are used for macro definitions. So, you may want to set that size on the top of your file, for example:
#define BUFFER_SIZE 1000
In that case the line char BUFFER_SIZE; is not needed anymore.
You use function insert_item before its declaration. So, to compile that you may put forward declaration also on top before producer():
int insert_item(buffer_item item);
That should be enough to compile the code.
Updated for new errors
Type declaration uses special keyword typedef to create type alias. Here to declare that buffer_item name is used as a type name and it is the same as char it should be exactly:
typedef char buffer_item;
The buffer array should be defined below as:
buffer_item buffer[BUFFER_SIZE];
Forward function declaration requires semicolon at the end:
int insert_item(buffer_item item);
I'm not sure that it will work as expected, but now it should be compiled.
Why this code give me different outputs every time?
Why it doesnt finish the loop?
What should I do to make it finish the loop? (despite context switches)?
Anything else I'm doing wrong?
Any help would be appreciated!
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#define MAX 10
int buffer[MAX];
int fill = 0;
int use = 0;
int count = 0;
int loops = 15;
void put(int value) {
buffer[fill] = value;
fill = (fill + 1) % MAX;
count++;
printf("putting %d\n", value);
}
int get() {
int tmp = buffer[use];
use = (use + 1) % MAX;
count--;
return tmp;
}
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t c_empty = PTHREAD_COND_INITIALIZER;
pthread_cond_t c_fill = PTHREAD_COND_INITIALIZER;
void *producer(void *arg) {
printf("producer starts\n");
int i;
for (i = 0; i < loops; i++) {
pthread_mutex_lock(&mutex); // p1
while (count == MAX) // p2
pthread_cond_wait(&c_empty, &mutex); // p3
put(i); // p4
pthread_cond_signal(&c_fill); // p5
pthread_mutex_unlock(&mutex); // p6
}
return NULL;
}
void *consumer(void *arg) {
printf("consumer starts\n");
int i;
for (i = 0; i < loops; i++) {
pthread_mutex_lock(&mutex); // c1
while (count == 0) // c2
pthread_cond_wait(&c_fill, &mutex); // c3
int tmp = get(); // c4
pthread_cond_signal(&c_empty); // c5
pthread_mutex_unlock(&mutex); // c6
printf("consuming: %d\n", tmp);
}
return NULL;
}
int main(int argc, char *argv[]) {
printf("parent: begin\n");
pthread_t p, x;
pthread_create(&p, NULL, producer, NULL);
pthread_create(&x, NULL, consumer, NULL);
printf("parent: end\n");
return 0;
}
Makefile:
all: wcountb
wcountb: wcountb.c
gcc -g -Wall -o wcountb wcountb.c -lpthread
At the end of the main, you should call for pthread_join, like this:
...
pthread_join(p, NULL);
pthread_join(x, NULL);
return 0;
}
Without that call, the threads are created and when you reach the end of main(), then your program terminates, thus your threads may be able to finish their job, or not, which explains the fact that sometimes your code works.
The pthread_join() function shall suspend execution of the calling thread until the target thread terminates, unless the target thread has already terminated.
Taken from the manual of pthread_join().
An almost related question lies here.