C/C++ threads magic difference in condition - c++

I wanted to write simple multithread app in C/C++. Function funProducent produces 100 values and if random generated value is in given range, char is added to buffer. Function funKonzument comsumes values from buffer. Here is my code:
#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
#define BUFFER_LIMIT 20
struct struktura{
pthread_mutex_t mutex;
pthread_cond_t bufferNotFull;
pthread_cond_t bufferNotEmpty;
int bufferIndex;
char * buffer;
int junk;
};
void * funProducent(void *arg){
struktura * data = (struktura *) arg;
int i = 0;
while (i < 100) {
pthread_mutex_lock(&data->mutex);
if(data->bufferIndex == BUFFER_LIMIT - 1){
pthread_cond_wait(&data->bufferNotFull, &data->mutex);
}
int randomValue = (rand() % 20) + 1;
if( randomValue < 13 ){
data->buffer[++data->bufferIndex] = 'a';
printf("%2d : Producent at index %d added %c\n", i, data->bufferIndex, data->buffer[data->bufferIndex]);
pthread_cond_signal(&data->bufferNotEmpty);
} else {
data->junk++;
}
pthread_mutex_unlock(&data->mutex);
i++;
}
printf("producent is done\n");
}
void * funKonzument(void *arg){
struktura * data = (struktura *) arg;
int i = 0;
while (i + data->junk < 100) {
printf("%d\n", i + data->junk);
pthread_mutex_lock(&data->mutex);
if(data->bufferIndex < 0){
pthread_cond_wait(&data->bufferNotEmpty, &data->mutex);
}
printf("%2d : Konzument at index %d consumed %c\n", i, data->bufferIndex, data->buffer[data->bufferIndex]);
data->bufferIndex--;
pthread_cond_signal(&data->bufferNotFull);
pthread_mutex_unlock(&data->mutex);
i++;
}
printf("konzument is done\n");
}
int main(int argc, char** argv) {
pthread_t threadProducent, threadKonzument;
struktura threadData;
threadData.buffer = (char *) malloc(sizeof(char) * BUFFER_LIMIT);
threadData.bufferIndex = -1;
threadData.bufferNotFull = PTHREAD_COND_INITIALIZER;
threadData.bufferNotEmpty = PTHREAD_COND_INITIALIZER;
threadData.mutex = PTHREAD_MUTEX_INITIALIZER;
threadData.junk = 0;
pthread_create(&threadProducent, NULL, funProducent, &threadData);
pthread_create(&threadKonzument, NULL, funKonzument, &threadData);
pthread_join(threadProducent, NULL);
pthread_join(threadKonzument, NULL);
free(threadData.buffer);
pthread_mutex_destroy(&threadData.mutex);
pthread_cond_destroy(&threadData.bufferNotFull);
pthread_cond_destroy(&threadData.bufferNotEmpty);
return 0;
}
When I try to run this code, sometimes it stucks in funKonzument at this line:
pthread_cond_wait(&data->bufferNotEmpty, &data->mutex);
But...when I change condition in funProducent method from:
if( randomValue < 13 )
to
if( randomValue > 8 )
everything works fine. Is anyone able to explain me what magic difference is between this two conditions?

You are probably suffering from spurious wakes and some problem with the junk counter. I just removed that counter and added a cond wait loop function (and a little lock context manager) and then the hangings seems to have stopped.
#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
#include <stdexcept>
#include <functional>
#define BUFFER_LIMIT 20
struct struktura{
pthread_mutex_t mutex;
pthread_cond_t bufferNotFull;
pthread_cond_t bufferNotEmpty;
int bufferIndex;
char * buffer;
};
// a lock context manager
class mlock {
pthread_mutex_t* mtx;
public:
mlock(pthread_mutex_t& Mtx) :
mtx(&Mtx)
{
int rv=pthread_mutex_lock(mtx);
if(rv) throw std::runtime_error(std::to_string(rv));
}
mlock(const mlock&) = delete;
mlock(mlock&&) = delete;
mlock& operator=(const mlock&) = delete;
mlock& operator=(mlock&&) = delete;
~mlock() {
pthread_mutex_unlock(mtx);
}
};
// silly loop to take care of spurious wakes
void cwait(pthread_cond_t& c, pthread_mutex_t& m, std::function<bool()> f) {
while(f()) pthread_cond_wait(&c, &m);
}
void* funProducent(void *arg){
struktura* data = static_cast<struktura*>(arg);
int i = 0;
while(i < 100) {
mlock dummy(data->mutex);
cwait(data->bufferNotFull, data->mutex, [&](){return data->bufferIndex == BUFFER_LIMIT - 1;});
int randomValue = (rand() % 20) + 1;
if( randomValue < 13 ){
data->buffer[++data->bufferIndex] = 'a';
printf("%2d : Producent at index %d added %c\n", i, data->bufferIndex, data->buffer[data->bufferIndex]);
i++;
pthread_cond_signal(&data->bufferNotEmpty);
}
}
printf("producent is done\n");
return nullptr;
}
void* funKonzument(void *arg){
struktura* data = static_cast<struktura*>(arg);
int i = 0;
while(i < 100) {
mlock dummy(data->mutex);
cwait(data->bufferNotEmpty, data->mutex, [&](){return data->bufferIndex<0;});
printf("\t\t\t%2d : Konzument at index %d consumed %c\n", i, data->bufferIndex, data->buffer[data->bufferIndex]);
data->bufferIndex--;
i++;
pthread_cond_signal(&data->bufferNotFull);
}
printf("\t\t\tkonzument is done\n");
return nullptr;
}
int main() {
pthread_t threadProducent, threadKonzument;
struktura threadData;
threadData.buffer = (char *) malloc(sizeof(char) * BUFFER_LIMIT);
threadData.bufferIndex = -1;
threadData.bufferNotFull = PTHREAD_COND_INITIALIZER;
threadData.bufferNotEmpty = PTHREAD_COND_INITIALIZER;
threadData.mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_create(&threadProducent, NULL, funProducent, &threadData);
pthread_create(&threadKonzument, NULL, funKonzument, &threadData);
pthread_join(threadProducent, NULL);
pthread_join(threadKonzument, NULL);
free(threadData.buffer);
pthread_mutex_destroy(&threadData.mutex);
pthread_cond_destroy(&threadData.bufferNotFull);
pthread_cond_destroy(&threadData.bufferNotEmpty);
return 0;
}

Related

Do I use memory barrier the wrong way?

I simply implement Peterson Lock Algorithm, but it doesn't work rightly.
Here is the code:
#include <pthread.h>
typedef struct {
volatile bool flag[2];
volatile bool victim;
} peterson_lock_t;
void peterson_lock_init(peterson_lock_t &lock) {
lock.flag[0] = lock.flag[1] = false;
lock.victim = 0;
}
void peterson_lock(peterson_lock_t &lock, int id) {
lock.victim = id;
lock.flag[id] = true;
__asm__ __volatile__("" : : : "memory");
while (lock.flag[1 - id] == false && lock.victim != id);
}
void peterson_unlock(peterson_lock_t &lock, int id) {
lock.flag[id] = false;
}
What's wrong with this code?
main.cpp:
#include <stdio.h>
#include "peterson_lock.h"
peterson_lock_t lock;
int count = 0;
void *routine0(void *arg) {
int *cnt = (int *)arg;
for (int i = 0; i < *cnt; ++i) {
peterson_lock(lock, 0);
++count;
peterson_unlock(lock, 0);
}
return NULL;
}
void *routine1(void *arg) {
int *cnt = (int *)arg;
for (int i = 0; i < *cnt; ++i) {
peterson_lock(lock, 1);
++count;
peterson_unlock(lock, 1);
}
}
int main(int argc, char **argv) {
peterson_lock_init(lock);
pthread_t thread0, thread1;
int count0 = 10000;
int count1 = 20000;
pthread_create(&thread0, NULL, routine0, (void *)&count0);
pthread_create(&thread1, NULL, routine1, (void *)&count1);
pthread_join(thread0, NULL);
pthread_join(thread1, NULL);
printf("Expected: %d\n", (count0 + count1));
printf("Reality : %d\n", count);
return 0;
}
And the result is not right:
Expected: 30000
Reality : 24304
Expected: 30000
Reality : 24316
OS:
Linux ip-172-31-43-244 3.14.35-28.38.amzn1.x86_64 #1 SMP Wed Mar 11 22:50:37 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux
While condition also needs to be improved :
while (lock.flag[1 - id] == true && lock.victim == id)
continue;
Be in busy wait until the other thread has lock and you are the victim.
Peterson Lock

Pthreads pool, keeping 1000 opened threads, pthread_create() returns 11

Need some help with PTHREADS. I want to keep over 1000 threads opened at any time, something like a thread pool. Here is the code :
/*
gcc -o test2 test2.cpp -static -lpthread -lstdc++
*/
#include <iostream>
#include <cstdlib>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <cstring>
#include <stdexcept>
#include <cstdlib>
int NUM_THREADS = 2000;
int MAX_THREADS = 100;
int THREADSTACK = 65536;
struct thread_struct{
int arg1;
int arg2;
};
pthread_mutex_t mutex_;
static unsigned int thread_count = 0;
string exec(const char* cmd)
{
int DEBUG=0;
char buffer[5000];
string result = "";
FILE* pipe = popen(cmd, "r");
if (!pipe && DEBUG) throw runtime_error("popen() failed!");
try
{
while (!feof(pipe))
{
if (fgets(buffer, 128, pipe) != NULL)
{
result += buffer;
}
}
}
catch(...)
{
pclose(pipe);
throw;
}
pclose(pipe);
return result;
}
void *thread_test(void *arguments)
{
pthread_mutex_lock(&mutex_);
thread_count++;
pthread_mutex_unlock(&mutex_);
// long tid;
// tid = (long)threadid;
struct thread_struct *args = (thread_struct*)arguments;
/*
printf("ARG1=%d\n",args->arg1);
printf("ARG2=%d\n",args->arg2);
*/
int thread_id = (int) args->arg1;
/*
int random_sleep;
random_sleep = rand() % 10 + 1;
printf ("RAND=[%d]\n", random_sleep);
sleep(random_sleep);
*/
int random_sleep;
random_sleep = rand() % 10 + 5;
// printf ("RAND=[%d]\n", random_sleep);
char command[100];
memset(command,0,sizeof(command));
sprintf(command,"sleep %d",random_sleep);
exec(command);
random_sleep = rand() % 100000 + 500000;
usleep(random_sleep);
// simulation of a work between 5 and 10 seconds
// sleep(random_sleep);
// printf("#%d -> sleep=%d total_threads=%u\n",thread_id,random_sleep,thread_count);
pthread_mutex_lock(&mutex_);
thread_count--;
pthread_mutex_unlock(&mutex_);
pthread_exit(NULL);
}
int main()
{
// pthread_t threads[NUM_THREADS];
int rc;
int i;
usleep(10000);
srand ((unsigned)time(NULL));
unsigned int thread_count_now = 0;
pthread_attr_t attrs;
pthread_attr_init(&attrs);
pthread_attr_setstacksize(&attrs, THREADSTACK);
pthread_mutex_init(&mutex_, NULL);
for( i=0; i < NUM_THREADS; i++ )
{
create_thread:
pthread_mutex_lock(&mutex_);
thread_count_now = thread_count;
pthread_mutex_unlock(&mutex_);
// printf("thread_count in for = [%d]\n",thread_count_now);
if(thread_count_now < MAX_THREADS)
{
printf("CREATE thread [%d]\n",i);
struct thread_struct struct1;
struct1.arg1 = i;
struct1.arg2 = 999;
pthread_t temp_thread;
rc = pthread_create(&temp_thread, NULL, &thread_test, (void *)&struct1);
if (rc)
{
printf("Unable to create thread %d\n",rc);
sleep(1);
pthread_detach(temp_thread);
goto create_thread;
}
}
else
{
printf("Thread POOL full %d of %d\n",thread_count_now,MAX_THREADS);
sleep(1);
goto create_thread;
}
}
pthread_attr_destroy(&attrs);
pthread_mutex_destroy(&mutex_);
// pthread_attr_destroy(&attrs);
printf("Proccess completed!\n");
pthread_exit(NULL);
return 1;
}
After spawning 300 threads it begins to give
errors, return code from pthread_create() is 11, and after that keeps executing them one by one.
What im i doing wrong?
According to this website, error code 11 corresponds to EAGAIN which means according to this:
Insufficient resources to create another thread.
A system-imposed limit on the number of threads was encountered.
Hence to solve your problem either create less threads or wait for running ones to finish before creating new ones.
You can also change default thread stack size see pthread_attr_setstacksize

How to asynchronously read/write in C++?

How do you copy one stream to another using dedicated read/write threads in C++?
Let's say I have these methods (not real, but to illustrate the point) to read/write data from. These read/write functions could represent anything (network/file/USB/serial/etc).
// returns the number of bytes read
void read(char* buffer, int bufferSize, int* bytesRead);
// returns the number of bytes written
void write(char* buffer, int bufferSize, int* bytesWritten);
The solution should also be portable.
NOTE: I am aware that Windows has a FILE_FLAG_OVERLAPPED feature, but this assumes that the read/write is file IO. Remember, these read/write methods could represent anything.
Here is the solution I came up with.
Header
#pragma once
#include <stdlib.h>
#include <queue>
#include <mutex>
#include <thread>
#include <chrono>
#include <list>
#include <thread>
#define ASYNC_COPY_READ_WRITE_SUCCESS 0
struct BufferBlock;
struct ReadStream
{
// read a stream to a buffer.
// return non-zero if error occured
virtual int read(char* buffer, int bufferSize, int* bytesRead) = 0;
};
struct WriteStream
{
// write a buffer to a stream.
// return non-zero if error occured
virtual int write(char* buffer, int bufferSize, int* bytesWritten) = 0;
};
class BufferBlockManager
{
public:
BufferBlockManager(int numberOfBlocks, int bufferSize);
~BufferBlockManager();
void enqueueBlockForRead(BufferBlock* block);
void dequeueBlockForRead(BufferBlock** block);
void enqueueBlockForWrite(BufferBlock* block);
void dequeueBlockForWrite(BufferBlock** block);
void resetState();
private:
std::list<BufferBlock*> blocks;
std::queue<BufferBlock*> blocksPendingRead;
std::queue<BufferBlock*> blocksPendingWrite;
std::mutex queueLock;
std::chrono::milliseconds dequeueSleepTime;
};
void AsyncCopyStream(BufferBlockManager* bufferBlockManager, ReadStream* readStream, WriteStream* writeStream, int* readResult, int* writeResult);
CPP
#include "AsyncReadWrite.h"
struct BufferBlock
{
BufferBlock(int bufferSize) : buffer(NULL)
{
this->bufferSize = bufferSize;
this->buffer = new char[bufferSize];
this->actualSize = 0;
this->isLastBlock = false;
}
~BufferBlock()
{
this->bufferSize = 0;
free(this->buffer);
this->buffer = NULL;
this->actualSize = 0;
}
char* buffer;
int bufferSize;
int actualSize;
bool isLastBlock;
};
BufferBlockManager::BufferBlockManager(int numberOfBlocks, int bufferSize)
{
dequeueSleepTime = std::chrono::milliseconds(100);
for (int x = 0; x < numberOfBlocks; x++)
{
BufferBlock* block = new BufferBlock(bufferSize);
blocks.push_front(block);
blocksPendingRead.push(block);
}
}
BufferBlockManager::~BufferBlockManager()
{
for (std::list<BufferBlock*>::const_iterator iterator = blocks.begin(), end = blocks.end(); iterator != end; ++iterator) {
delete (*iterator);
}
}
void BufferBlockManager::enqueueBlockForRead(BufferBlock* block)
{
queueLock.lock();
block->actualSize = 0;
block->isLastBlock = false;
blocksPendingRead.push(block);
queueLock.unlock();
}
void BufferBlockManager::dequeueBlockForRead(BufferBlock** block)
{
WAITFOR:
while (blocksPendingRead.size() == 0)
std::this_thread::sleep_for(dequeueSleepTime);
queueLock.lock();
if (blocksPendingRead.size() == 0)
{
queueLock.unlock();
goto WAITFOR;
}
*block = blocksPendingRead.front();
blocksPendingRead.pop();
queueLock.unlock();
}
void BufferBlockManager::enqueueBlockForWrite(BufferBlock* block)
{
queueLock.lock();
blocksPendingWrite.push(block);
queueLock.unlock();
}
void BufferBlockManager::dequeueBlockForWrite(BufferBlock** block)
{
WAITFOR:
while (blocksPendingWrite.size() == 0)
std::this_thread::sleep_for(dequeueSleepTime);
queueLock.lock();
if (blocksPendingWrite.size() == 0)
{
queueLock.unlock();
goto WAITFOR;
}
*block = blocksPendingWrite.front();
blocksPendingWrite.pop();
queueLock.unlock();
}
void BufferBlockManager::resetState()
{
queueLock.lock();
blocksPendingRead = std::queue<BufferBlock*>();
blocksPendingWrite = std::queue<BufferBlock*>();
for (std::list<BufferBlock*>::const_iterator iterator = blocks.begin(), end = blocks.end(); iterator != end; ++iterator) {
(*iterator)->actualSize = 0;
}
queueLock.unlock();
}
struct AsyncCopyContext
{
AsyncCopyContext(BufferBlockManager* bufferBlockManager, ReadStream* readStream, WriteStream* writeStream)
{
this->bufferBlockManager = bufferBlockManager;
this->readStream = readStream;
this->writeStream = writeStream;
this->readResult = ASYNC_COPY_READ_WRITE_SUCCESS;
this->writeResult = ASYNC_COPY_READ_WRITE_SUCCESS;
}
BufferBlockManager* bufferBlockManager;
ReadStream* readStream;
WriteStream* writeStream;
int readResult;
int writeResult;
};
void ReadStreamThread(AsyncCopyContext* asyncContext)
{
int bytesRead = 0;
BufferBlock* readBuffer = NULL;
int readResult = ASYNC_COPY_READ_WRITE_SUCCESS;
while (
// as long there hasn't been any write errors
asyncContext->writeResult == ASYNC_COPY_READ_WRITE_SUCCESS
// and we haven't had an error reading yet
&& readResult == ASYNC_COPY_READ_WRITE_SUCCESS)
{
// let's deque a block to read to!
asyncContext->bufferBlockManager->dequeueBlockForRead(&readBuffer);
readResult = asyncContext->readStream->read(readBuffer->buffer, readBuffer->bufferSize, &bytesRead);
readBuffer->actualSize = bytesRead;
readBuffer->isLastBlock = bytesRead == 0;
if (readResult == ASYNC_COPY_READ_WRITE_SUCCESS)
{
// this was a valid read, go ahead and queue it for writing
asyncContext->bufferBlockManager->enqueueBlockForWrite(readBuffer);
}
else
{
// an error occured reading
asyncContext->readResult = readResult;
// since an error occured, lets queue an block to write indicatiting we are done and there are no more bytes to read
readBuffer->isLastBlock = true;
readBuffer->actualSize = 0;
asyncContext->bufferBlockManager->enqueueBlockForWrite(readBuffer);
}
if (readBuffer->isLastBlock) return;
}
}
void WriteStreamThread(AsyncCopyContext* asyncContext)
{
int bytesWritten = 0;
BufferBlock* writeBuffer = NULL;
int writeResult = ASYNC_COPY_READ_WRITE_SUCCESS;
bool isLastWriteBlock = false;
while (
// as long as there are no errors during reading
asyncContext->readResult == ASYNC_COPY_READ_WRITE_SUCCESS
// and we haven't had an error writing yet
&& writeResult == ASYNC_COPY_READ_WRITE_SUCCESS)
{
// lets dequeue a block for writing!
asyncContext->bufferBlockManager->dequeueBlockForWrite(&writeBuffer);
isLastWriteBlock = writeBuffer->isLastBlock;
if (writeBuffer->actualSize > 0)
writeResult = asyncContext->writeStream->write(writeBuffer->buffer, writeBuffer->actualSize, &bytesWritten);
if (writeResult == ASYNC_COPY_READ_WRITE_SUCCESS)
{
asyncContext->bufferBlockManager->enqueueBlockForRead(writeBuffer);
if (isLastWriteBlock) return;
}
else
{
asyncContext->writeResult = writeResult;
asyncContext->bufferBlockManager->enqueueBlockForRead(writeBuffer);
return;
}
}
}
void AsyncCopyStream(BufferBlockManager* bufferBlockManager, ReadStream* readStream, WriteStream* writeStream, int* readResult, int* writeResult)
{
AsyncCopyContext asyncContext(bufferBlockManager, readStream, writeStream);
std::thread readThread(ReadStreamThread, &asyncContext);
std::thread writeThread(WriteStreamThread, &asyncContext);
readThread.join();
writeThread.join();
*readResult = asyncContext.readResult;
*writeResult = asyncContext.writeResult;
}
Usage
#include <stdio.h>
#include <tchar.h>
#include "AsyncReadWrite.h"
struct ReadTestStream : ReadStream
{
int readCount = 0;
int read(char* buffer, int bufferSize, int* bytesRead)
{
printf("Starting read...\n");
memset(buffer, bufferSize, 0);
if (readCount == 10)
{
*bytesRead = 0;
return 0;
}
// pretend this function takes a while!
std::this_thread::sleep_for(std::chrono::milliseconds(100));
char buff[100];
sprintf_s(buff, "This is read number %d\n", readCount);
strcpy_s(buffer, sizeof(buff), buff);
*bytesRead = strlen(buffer);
readCount++;
printf("Finished read...\n");
return 0;
}
};
struct WriteTestStream : WriteStream
{
int write(char* buffer, int bufferSize, int* bytesWritten)
{
printf("Starting write...\n");
// pretend this function takes a while!
std::this_thread::sleep_for(std::chrono::milliseconds(500));
printf(buffer);
printf("Finished write...\n");
return 0;
}
};
int _tmain(int argc, _TCHAR* argv[])
{
BufferBlockManager bufferBlockManager(5, 4096);
ReadTestStream readStream;
WriteTestStream writeStream;
int readResult = 0;
int writeResult = 0;
printf("Starting copy...\n");
AsyncCopyStream(&bufferBlockManager, &readStream, &writeStream, &readResult, &writeResult);
printf("Finished copy... readResult=%d writeResult=%d \n", readResult, writeResult);
getchar();
return 0;
}
EDIT: I put my solution into a GitHub repository here. If you wish to use this code, refer to the repository since it may be more updated than this answer.
Typically, you would just have one thread for each direction that alternates between reads and writes.

Dead lock pthread C++ with signaling

I need 2 threads: TC and TS, such that they are composed in two main sections each accessing shared data and the threads must to be synchronized. The synchronization should be like this:
The red codes are working with shared data U, but get U can be placed before the dashed rectangle on the TS thread, riht side.
The Xcurrent can be in TC or in TS the tasks, but is a shared hardware with send Ucurrent and get must be right after send was finished.
A dead lock appears and I can't figure out an elegant solution.
Thread TS:
#include <stdio.h> /* printf, scanf, NULL */
#include <stdlib.h> /* malloc, free, rand */
#define _USE_MATH_DEFINES
#include <math.h>
#include <windows.h>
#include <pthread.h>
#include <time.h>
// CRLT-C var
static int stop = 0;
// TIMEING vars
__int64 frequencyT, startT, endT = 0;
double baseAngleLast;
double pendulAngleLast;
// THREADING vars
bool startedS = false, Usent = false;
double * Ucmd;
pthread_mutex_t mutexU = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t mutexBoard = PTHREAD_MUTEX_INITIALIZER;
unsigned int Ulenght = 6;
pthread_cond_t signal_to_read_state = PTHREAD_COND_INITIALIZER;
pthread_cond_t signal_to_read_cmd = PTHREAD_COND_INITIALIZER;
DWORD sleepTime = 30; // in milliseconds
int currentState = 3;
void *sendingCMD(void * )
{
double * U_tmp;
U_tmp = (double*)malloc(sizeof(double)*Ulenght);
startedS = true;
printf("Sin\n");
while (stop == 0)
{
printf("Smu-\n");
//get U
pthread_mutex_lock( &mutexU );
printf("Smu..\n");
pthread_cond_wait(&signal_to_read_cmd, &mutexU);
memcpy(U_tmp,Ucmd,sizeof(double)*Ulenght);
pthread_mutex_unlock( &mutexU );
printf("Smu+\n");
pthread_mutex_lock( &mutexBoard );
for (unsigned int i = 0; i<Ulenght; i++)
{
//send CMD signal
printf("%f ", U_tmp[i]);
if (i == Ulenght -1) printf("\n");
}
Sleep(sleepTime); // miliseconds
currentState = currentState + 1;
pthread_cond_signal(&signal_to_read_state);
pthread_mutex_unlock( &mutexBoard );
printf("Smb\n");
}
printf("Task S terminated. \n");
return (NULL);
}
void *computingU(void *)
{
double * U_tmp;
U_tmp = (double*)malloc(sizeof(double)*Ulenght);
int currentStateTMP =0;
bool fisrtLoop = true;
printf("Uin\n");
while (stop == 0)
{
printf("Umb- \n");
// get current state
pthread_mutex_lock( &mutexBoard );
if (!fisrtLoop)
{
printf("UmbFalse \n");
pthread_cond_wait(&signal_to_read_state, &mutexBoard);
}
else
{
printf("UmbTrue \n");
fisrtLoop=false;
}
currentStateTMP =currentState;
pthread_mutex_unlock( &mutexBoard );
printf("Umb+ \n");
pthread_mutex_lock( &mutexU );
for (unsigned int i=0;i<Ulenght;i++)
{
Ucmd[i] = Ucmd[i]+ (double)currentStateTMP/i;
}
pthread_cond_signal(&signal_to_read_cmd);
pthread_mutex_unlock( &mutexU );
printf("Umu\n");
}
return (NULL);
}
void signal_handler(int signal)
{
stop = 1;
}
int main(int argc, char* argv[])
{
//initializing output buffer to 0[V]
Ucmd= (double*)malloc(sizeof(double)*Ulenght);
for (unsigned int i=0;i<Ulenght;i++)
Ucmd[i] = 0;
//init threads
int rc1, rc2;
pthread_t threadU, threadS;
/* Create independent threads each of which will execute functionC */
if( (rc1=pthread_create( &threadU, NULL, &computingU, NULL)) ) {
printf("ThreadU creation failed: %d\n", rc1);
}
if( (rc2=pthread_create( &threadS, NULL, &sendingCMD, NULL)) )
{
printf("ThreadS creation failed: %d\n", rc2);
}
while (stop == 0);
printf("Main terminated, closing board in 10ms. \n");
Sleep(10);
return 0;
}
The blocking appears at:
TC at pthread_cond_wait(&signal_to_read_state, &mutexBoard);
TS at pthread_cond_wait(&signal_to_read_cmd, &mutexU);
btw why dose not recognize stackoverflow the code segment I pasted above in case i copy paste from a VS2010?

Producer-Consumer Issue

Hi I'm trying to write an algorithm for solving the producer-consumer problem and I've hit a roadblock. This is the output I am getting from my code:
Producing: 6
6 0 0 0 0 0 0 0 0 0 END
and then the program exits. I'm not sure where I went wrong? Did I do something wrong in creating a circular buffer?
#include <iostream>
#include <pthread.h>
#include <semaphore.h>
#include <pthread.h>
#include <stdlib.h>
#include <stdio.h>
#include <string>
#include <fstream>
using namespace std;
#define BUFFER_SIZE 10
void *produce(void *);
void *consume(void *);
int produceItem(void);
void insertItem(int item);
void removeItem(void);
void printBuffer(void);
int head = 0;
int tail = 0;
int item;
int bufferCount = 0;
pthread_t producer, consumer;
pthread_cond_t Buffer_Not_Full=PTHREAD_COND_INITIALIZER;
pthread_cond_t Buffer_Not_Empty=PTHREAD_COND_INITIALIZER;
pthread_mutex_t lock;
sem_t sem_filledSlots;
sem_t sem_emptySlots;
int buffer[BUFFER_SIZE];
int main() {
int emptyCount;
int item;
srand (time(NULL));
sem_init(&sem_filledSlots, 0, 0);
sem_init(&sem_emptySlots, 0, BUFFER_SIZE);
sem_getvalue(&sem_emptySlots, &emptyCount);
pthread_create (&producer, NULL, &produce, NULL);
pthread_create (&consumer, NULL, &consume, NULL);
return 0;
}
void *produce(void *)
{
for(int i = 0; i <15; i++)
{
item = produceItem();
sem_wait(&sem_emptySlots);
pthread_mutex_lock(&lock);
printf("Producing: %d \n", item);
buffer[head] = item;
head = (head + 1) % BUFFER_SIZE;
printBuffer();
pthread_mutex_unlock(&lock);
sem_post(&sem_filledSlots);
}
}
void *consume(void *)
{
for(int i = 0; i <15; i++)
{
sem_wait(&sem_filledSlots);
pthread_mutex_lock(&lock);
printf("Consuming %d \n", buffer[tail]);
buffer[tail] = 0;
tail = (tail + 1) % BUFFER_SIZE;
bufferCount--;
printBuffer();
pthread_mutex_unlock(&lock);
sem_post(&sem_emptySlots);
}
}
int produceItem(void)
{
int x = (rand()%11 + 1);
return x;
}
void printBuffer(void)
{
for(int i = 0; i <BUFFER_SIZE; i++)
{
printf("%d ", buffer[i]);
}
printf("END \n");
}
you're missing pthread_join before exiting the program:
....
pthread_join(producer,NULL);
pthread_join(consumer,NULL);
return 0;
....