stl map simultaneous write sample code - c++

I want to simulate the abnormal behavior of stl map in simultaneous write condition.
Here I am using a single map and simultaneously inserting data from multiple threads.
As we are using only one map object, hence it should not allow.
Please go through the following sample code
#include <iostream>
#include <map>
#include <iterator>
#include <algorithm>
extern "C"
{
#include <pthread.h>
#include <string.h>
#include <stdlib.h>
}
using namespace std;
//functor to print map
struct PrintMp
{
void operator()(pair<int,int> pr)
{
cout<<pr.first<<" => "<<pr.second<<endl;
}
};
//thread 1
//inserts continuous no from 0 to 4999
void* ins_th1(void *arg)
{
map<int, int> *mp = static_cast<map<int, int>* >(arg);
for(int i =0 ; i<5000; i++)
mp->insert(pair<int,int>(i, i+1000));
return NULL;
}
//thread 1
//inserts continuous no from 0 to 4999
void* ins_th2(void *arg)
{
map<int, int> *mp = static_cast<map<int,int>* >(arg);
for(int i=5000; i<10000; i++)
mp->insert(pair<int, int>(i, i+2000));
return NULL;
}
int main()
{
typedef map<int, int> IntMapType;
IntMapType mp;
PrintMp MpPrintObj;
int rc;
pthread_t th1, th2;
//thread 1 creation
rc = pthread_create(&th1, NULL, ins_th1, static_cast<void*>(&mp));
if ( rc != 0)
{
cerr<<strerror(rc)<<"in thread1"<<endl;
exit(EXIT_FAILURE);
}
//thread 2 creation
rc = pthread_create(&th2, NULL, ins_th2, static_cast<void*>(&mp));
if(rc!=0)
{
cerr<<strerror(rc)<<"in thread2"<<endl;
exit(EXIT_FAILURE);
}
//lets wait for the thread to finish
rc = pthread_join(th1, NULL);
if ( rc != 0)
{
cerr<<strerror(rc)<<"join failure for thread1"<<endl;
exit(EXIT_FAILURE);
}
rc = pthread_join(th2, NULL);
if ( rc != 0)
{
cerr<<strerror(rc)<<"join failure for thread2"<<endl;
exit(EXIT_FAILURE);
}
cout<<"Map data"<<endl;
//now print it
for_each(mp.begin(), mp.end(), MpPrintObj);
cout<<endl;
return 0;
}
But it doesn't work. Can anyone suggest me some approach ?

You are only testing insertion, which may or may not be implemented in a thread safe fashion, for all you know. But, your test is not complete. Allow the threads to write the same key into the map, and you will likely experience an error that would not happen without multiple threads.
// ins_th1
for(int i =0 ; i<10000; i++)
mp->insert(pair<int,int>(i, i+1000));
// ins_th2
for(int i=0; i<10000; i++)
mp->insert(pair<int, int>(i, i+2000));
You should test deletion from the map as well. When I modified your program to populate the map, before launching the threads, and only had the threads remove things from the map, the program live-locked.
// ins_th1
for(int i =0 ; i<5000; i++)
mp->erase(i);
// ins_th2
for(int i=5000; i<10000; i++)
mp->erase(i);
// near top of main
for(int i =0 ; i<5000; i++)
mp.insert(pair<int,int>(i, i+1000));
for(int i=5000; i<10000; i++)
mp.insert(pair<int, int>(i, i+2000));
//... launch threads

I tried to implement as you said.
But despite not using any synchronization mechanism, I am getting the perfect result.

Related

How to avoid global semaphores and queues when using threads

I have a problem with my code. It works, but I cannot avoid using global semaphores. I have 3 thread functions. the first is run by 10 threads. The second and third are run by 2 threads each. These threads should run without having race conditions. In addition, they should communicate with each other. I use a user defined queue class for communications between threads and between the threads and main. Also, I use the semaphores to achieve mutual exclusion between the threads. Since I declare the instance of the queue class and the semaphores in a global manner, I do not have to pass them to any function. They are accessible to any function in this program. However, this is not a healthy way to write programs. Therefore, I ask you, how to declare the queue and the semaphores locally, and what is the best way to pass them between threads.
// queueString header
#include <string>
#include <queue>
#include <semaphore.h>
using namespace std;
class queueString
{
public:
queueString();
~queueString();
void qPush(string str);
string qPop();
private:
sem_t queueSem;
queue <string> q;
};
//queueString class
#include "queueString.h"
using namespace std;
// queue class that will enqueue and dequeue atomically.
queueString::queueString(){
sem_init(&queueSem, 0, 1);
}
queueString::~queueString(){}
void queueString::qPush(string str){
sem_wait(&queueSem);
this->q.push(str);
sem_post(&queueSem);
}
string queueString::qPop(){
sem_wait(&queueSem);
string str = this->q.front();
q.pop();
sem_post(&queueSem);
return str;
}
//The three threads with main
#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <string>
#include <iostream>
#include "queueString.h"
using namespace std;
//My question is here, How to declare the variables below locally, and where
// is the right place to declare them, and how to pass them to threads?
sem_t s12, s13, s21, s31, sthr1, sthr2[2], sthr3[2], printSem;
sem_t idInitializationSemMainToThread, idInitializationSemThreadToMain;
queueString q = queueString();
#define THR1NUM 10
#define THR2NUM 2
#define THR3NUM 2
void printString(string str);
void *thread1(void* arg){
sem_wait(&idInitializationSemMainToThread);
int *pnum = (int *)arg;
int thr_1_ID = *pnum;
sem_post(&idInitializationSemThreadToMain);
sem_wait(&sthr1);
string value= "THR1 ";
value.append(to_string(thr_1_ID));
q.qPush(value);
sem_post(&s12);
sem_wait(&s21);
value= "2nd Iteration THR1 ";
value.append(to_string(thr_1_ID));
q.qPush(value);
sem_post(&s13);
sem_wait(&s31);
sem_post(&sthr1);
}
void *thread2(void* arg){
sem_wait(&idInitializationSemMainToThread);
int *pnum = (int *)arg;
int thr_2_ID = *pnum;
sem_post(&idInitializationSemThreadToMain);
while (true)
{
sem_wait(&sthr2[thr_2_ID]);
sem_wait(&s12);
string readVal = q.qPop();
printString(readVal + ", THR2 "+ to_string(thr_2_ID));
if (thr_2_ID==0)
sem_post(&sthr2[1]);
else
sem_post(&sthr2[0]);
sem_post(&s21);
}
}
void *thread3(void* arg){
sem_wait(&idInitializationSemMainToThread);
int *pnum = (int *)arg;
int thr_3_ID = *pnum;
sem_post(&idInitializationSemThreadToMain);
while (true)
{
sem_wait(&sthr3[thr_3_ID]);
sem_wait(&s13);
string readVal = q.qPop();
printString(readVal + " THR3 " + to_string(thr_3_ID));
if (thr_3_ID == 0)
sem_post(&sthr3[1]);
else
sem_post(&sthr3[0]);
sem_post(&s31);
}
}
int main(){
pthread_t thr1[THR1NUM], thr2[THR2NUM], thr3[THR3NUM];
sem_init(&s12, 0, 0);
sem_init(&s13, 0, 0);
sem_init(&s31, 0, 0);
sem_init(&s21, 0, 0);
sem_init(&printSem, 0, 1);
sem_init(&sthr1, 0, 0);
for (int i = 0; i < 2;i++)
sem_init(&sthr2[i], 0, 0);
for (int i = 0; i < 2;i++)
sem_init(&sthr3[i], 0, 0);
sem_init(&idInitializationSemMainToThread, 0, 0);
sem_init(&idInitializationSemThreadToMain, 0, 0);
int *pnum =(int *) malloc(sizeof(int));
for (int j = 0; j < THR2NUM;j++){
*pnum = j;
pthread_create(&thr2[j], NULL, thread2, (void *)pnum);
sem_post(&idInitializationSemMainToThread);
printString("thr2 "+to_string(j)+ " created");
sem_wait(&idInitializationSemThreadToMain);
}
for (int k = 0; k < THR3NUM;k++){
*pnum = k;
pthread_create(&thr3[k], NULL, thread3,(void *) pnum);
sem_post(&idInitializationSemMainToThread);
printString("thr3 "+to_string(k)+ " created");
sem_wait(&idInitializationSemThreadToMain);
}
for (int i = 0; i < THR1NUM;i++){
*pnum = i;
pthread_create(&thr1[i], NULL, thread1,(void *) pnum);
sem_post(&idInitializationSemMainToThread);
printString("thr1 "+to_string(i)+ " created");
sem_wait(&idInitializationSemThreadToMain);
}
sem_post(&sthr2[0]);
sem_post(&sthr3[0]);
sem_post(&sthr1);
for (int i = 0; i < THR1NUM;i++){
pthread_join(thr1[i], NULL);
printString("thr1 "+to_string(i)+ " joined");
}
for (int i = 0; i < THR2NUM; i++){
pthread_cancel(thr2[i]);
printString("thr2 "+to_string(i)+ " exited");
}
for (int i = 0; i < THR3NUM;i++){
pthread_cancel(thr3[i]);
printString("thr3 "+to_string(i)+ " exited");
sem_post(&printSem);
}
sem_destroy(&s12);
sem_destroy(&s21);
sem_destroy(&s13);
sem_destroy(&s31);
sem_destroy(&sthr1);
free(pnum);
}
// function to print strings atomically.
void printString(string str){
sem_wait(&printSem);
printf("%s\n", str.c_str());
sem_post(&printSem);
}

Pthread segment fault using pointer to variable in main

I'm new to pthread and attempting to implement a producer/consumer problem that will let the user pick buffer size, # of producers, # of consumers, and total # of items. I've been looking through what I thought were similar things on stack overflow, but can't seem to get it right.
My code has a main class and it spawns producers and consumers. It hands the producers and consumers a pointer to a stack initialized in main (or at least I'm trying to). I thought that what I was doing was legal and in CLion I get the predictive text options I want so I thought I linked it properly but I'm segfaulting when I try to read the top element.
I used GDB to make sure I knew what line I was crashing on, but don't understand what's wrong with my setup. While debugging I confirmed that a producer goes through its push() command first, but the consumer fails when attempting top() or pop(). I'd seen some threads here where the OP had problems because they didn't join their threads, but I am so I'm a little lost.
#include <iostream>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <stack>
#include <cstring>
#include <semaphore.h>
#include <pthread.h>
#define N 10000
sem_t mutex;
sem_t fullCount;
sem_t emptyCount;
int iCount = 0;
typedef struct _thread_data{
int id;
int itemcount;
std::stack<char>* ptr;
}thread_data;
void *producer(void *arg){
std::cout << "spawned producer\n";
thread_data *data = (thread_data *)arg;
while(true){
char message = 'X';
sem_wait(&emptyCount);
sem_wait(&mutex);
if(iCount < data->itemcount){
data->ptr->push(message);
iCount++;
char temp [25];
sprintf(temp, "p:<%u>, item: %c, at %d\n", data->id, message, data->ptr->size());
std::cout << temp;
//std::cout << "hi I'm a producer\n";
sem_post(&mutex);
sem_post(&fullCount);
}
else{
sem_post(&fullCount);
sem_post(&mutex);
pthread_exit(nullptr);
}
}
}
void *consumer(void *arg){
std::cout << ("spawned consumer\n");
thread_data *data = (thread_data *)arg;
while(true){
char message;
sem_wait(&fullCount);
sem_wait(&mutex);
if(iCount < data->itemcount) {
message = data->ptr->top(); //SEGFAULT
char temp[25];
printf(temp, "c:<%u>, item: %c, at %d\n", data->id, message, data->ptr->size());
data->ptr->pop();
std::cout << temp;
//std::cout << "Hi I'm a consumer\n";
sem_post(&mutex);
sem_post(&emptyCount);
}
else if (iCount == data->itemcount){
message = data->ptr->top(); //SEGFAULT
char temp[25];
printf(temp, "c:<%u>, item: %c, at %d\n", data->id, message, data->ptr->size());
data->ptr->pop();
std::cout << temp;
sem_post(&emptyCount);
sem_post(&mutex);
pthread_exit(nullptr);
}
else{
sem_post(&mutex);
pthread_exit(nullptr);
}
}
}
int main(int argc, char *argv[]){
int bufferSize = N;
int pThreadCount,cThreadCount,itemCount;
for (int x = 0; x < argc; ++x) {
if(strcmp(argv[x],"-b") == 0){
bufferSize = atoi(argv[x+1]);
}
if(strcmp(argv[x],"-p") == 0){
pThreadCount = atoi(argv[x+1]);
}
if(strcmp(argv[x],"-c") == 0){
cThreadCount = atoi(argv[x+1]);
}
if(strcmp(argv[x],"-i") == 0){
itemCount = atoi(argv[x+1]);
}
}
sem_init(&mutex,1,1);
sem_init(&fullCount,1,0);
sem_init(&emptyCount,1,bufferSize);
std::stack<char> myStack;
pthread_t myPThreads[pThreadCount];
thread_data thrData[pThreadCount];
pthread_t myCThreads[cThreadCount];
thread_data cThrData[cThreadCount];
for (int i = 0; i < pThreadCount; ++i) {
thrData[i].id = i;
thrData[i].itemcount = itemCount;
thrData[i].ptr = &myStack;
pthread_create(&myPThreads[i], NULL, producer, &thrData[i]);
}
for (int i = 0; i < cThreadCount; ++i) {
cThrData[i].id = i;
cThrData[i].itemcount = itemCount;
thrData[i].ptr = &myStack;
pthread_create(&myCThreads[i], NULL, consumer, &cThrData[i]);
}
for (int k = 0; k < pThreadCount; ++k) {
pthread_join(myPThreads[k], NULL);
}
for (int j = 0; j < cThreadCount; ++j) {
pthread_join(myCThreads[j], NULL);
}
return 0;
}
iCount <= data->itemcount is always true. consumer never exits the loop. At some point, it exhausts the stack, and the subsequent top() call exhibits undefined behavior.
cThrData[i].ptr is never initialized, for any i. consumer calls top() through an uninitialized pointer, whereupon the program exhibits undefined behavior.

edit string in multi thread

I am newer for c++, and I know in c++0x multithreading support is poor.
But now I have to edit a string val in multi thread, I use thread_mutex to protect the val. The problem is the program always core dump when runing.
Although after re-design I find a better solution but I can't figure out why it core. So could some one told me about what happend?
The code is like below
using namespace std;
const static int kThreadSize = 48;
map<string, string> gMap;
string gStr = "";
void * func(void * data)
{
while(true)
{
printf("%s\n", gStr.c_str());
pthread_mutex_t m;
pthread_mutex_init(&m, NULL);
pthread_mutex_lock(&m);
gStr = gStr + "a";//core in this line
printf("%x\n", &gStr);//print the address
pthread_mutex_unlock(&m);
pthread_mutex_destroy(&m);
printf("%s\n", gStr.c_str());
}
}
int main()
{
pthread_t threads[kThreadSize];
for(int i = 0; i < kThreadSize; i ++)
{
pthread_create(&threads[i], NULL, &func, &gMap);
}
for(int i = 0; i < kThreadSize; i ++)
{
pthread_join(threads[i], NULL);
}
return 0;
}
EDIT:
By using the global mutex will solve the problem pointed by Mike.Here I don't paste the new source code.
My new question is I also can't understand why it will core when edit a string in multithreading. Because of COW or reference count?
As i can see there is a problem with yours Mutex, because it is create into the method func() and it make that each thread invocation of func()create a new mutex, it is happened by each threat that invokes this method.
As MikeB says, i sugest you review the thread theory but, meanwhile, try to use a unique mutex to synchronize the access to gMap, as the example shows:
using namespace std;
const static int kThreadSize = 48;
map<string, string> gMap;
string gStr = "";
pthread_mutex_t m;
void * func(void * data)
{
while(true)
{
printf("%s\n", gStr.c_str());
pthread_mutex_lock(&m);
gStr = gStr + "a";//core in this line
printf("%x\n", &gStr);//print the address
pthread_mutex_unlock(&m);
printf("%s\n", gStr.c_str());
}
}
int main()
{
pthread_mutex_init(&m, NULL);
pthread_t threads[kThreadSize];
for(int i = 0; i < kThreadSize; i ++)
{
pthread_create(&threads[i], NULL, &func, &gMap);
}
for(int i = 0; i < kThreadSize; i ++)
{
pthread_join(threads[i], NULL);
}
return 0;
}

Parallel merge sort useing _beginthreadex windows API in C++

I'm trying to implement merge sort using win32 _beginthreadex multiple threads in c++. basically it uses _beginthreadex instead of function call to make recursion in each thread. so it will has as many threads as possible. the while loop after the two _beginthreadex call is to check if the children threads finish there job. But when the program access the array a and b, it gives an error that unable to read the memory, I can't find what the problem is. It seems that in the sorting section in children threads the program try to access invalid memory address that info->b goes to the address 0xcccccccc {???}
Thank you
#include "stdafx.h"
#include <windows.h>
#include <iostream>
#include <process.h>
#include <stdlib.h>
#include <time.h>
#include <string>
#include <sstream>
#include <array>
#include <stdio.h>
using namespace std;
struct ThreadInfo
{
int* a;
int* b;
int low;
int high;
bool run;
};
unsigned __stdcall mergesort(void* x) {
ThreadInfo* info = (ThreadInfo*)x;
if ((info->low) < (info->high))
{
int pivot = ((info->low)+(info->high))/2;
ThreadInfo lowInfo;
ThreadInfo highInfo;
lowInfo.a=info->a;
lowInfo.low=info->low;
lowInfo.high=pivot;
lowInfo.run=true;
highInfo.b=info->b;
highInfo.low=pivot+1;
highInfo.high=info->high;
highInfo.run=true;
//HANDLE myhandlerUp, myhandlerDown;
//creat sub-thread
_beginthreadex(NULL, 0, mergesort, &lowInfo, 0, 0);
//WaitForSingleObject(myhandlerUp,INFINITE);
_beginthreadex(NULL, 0, mergesort, &highInfo, 0, 0);
//WaitForSingleObject(myhandlerDown,INFINITE);
//check if any child threads are working
bool anyRun = true;
while (anyRun)
{
anyRun = false;
anyRun = lowInfo.run || highInfo.run;
}
//doing merge sort
int h,i,j,k,low, high;
low = info->low;
high = info->high;
h=low;
i=low;
j=pivot+1;
while((h<=pivot)&&(j<=high))
{
if(info->a[h]<=info->a[j])
{
info->b[i]=info->a[h];
h++;
}
else
{
info->b[i]=info->a[j];
j++;
}
i++;
}
if(h>pivot)
{
for(k=j; k<=high; k++)
{
info->b[i]=info->a[k];
i++;
}
}
else
{
for(k=h; k<=pivot; k++)
{
info->b[i]=info->a[k];
i++;
}
}
for(k=low; k<=high; k++) info->a[k]=info->b[k];
}
info->run = false;
return 0;
}
void main()
{
ThreadInfo info;
int inputArr[12] = {12,10,43,23,-78,45,123,56,98,41,90,24};
int copiedArr[12]={0,0,0,0,0,0,0,0,0,0,0,0};
info.a=inputArr;
info.b=copiedArr;
for(int i=0; i<12; i++)
cout<<info.a[i]<<" ";
cout<<endl;
info.low=0;
info.high=(11);
info.run=true;
_beginthreadex(NULL, 0, mergesort, &info, 0, 0);
bool finish = info.run;
while(finish){
cout<<"Running...."<<endl;
Sleep(1000);
}
cout<<"After run the result is "<<endl;
for(int i=0; i<12; i++)
cout<<inputArr[i]<<" ";
cout<<endl;
getchar();
}

c++ pthreads opertions on a global char buffer

I am experimenting with pthreads. I am trying to create three threads and have them operate on a global char buffer. I am using mutex lock and unlock for their critical sections. The program flow should go: Main spawns three threads. Thread one locks, initializes the buffer, prints it out, signals thread two, and unlocks. Thread two enters its critical section operates on the buffer and signals thread three, etc. It seems to work, sometimes. Other times, it seems like it is getting suck in a spin lock. Any help in the right direction would be great. Thanks.
#include <pthread.h>
#include <string.h>
#include <unistd.h>
#include <iostream>
using namespace std;
const int num_threads = 3;
char buffer[100];
pthread_mutex_t buffer_mutex = pthread_mutex_initializer;
pthread_cond_t buffer_cond = pthread_cond_initializer;
void* firstthreadfunc(void* proc) {
string a = "data received";
pthread_mutex_lock(&buffer_mutex);
sleep(1);
cout<<"threadone"<<endl;
for(int i = 0;i<14;i++){
buffer[i] = a[i];
cout<<buffer[i];
}
cout<<endl;
pthread_cond_signal(&buffer_cond);
pthread_mutex_unlock(&buffer_mutex);
return null;
}
void* secondthreadfunc(void* proc) {
string a = "data processed";
pthread_mutex_lock(&buffer_mutex);
pthread_cond_wait(&buffer_cond, &buffer_mutex);
sleep(1);
cout<<"threadtwo"<<endl;
for(int i = 0; i<15 ;i++){
buffer[i] = a[i];
cout<<buffer[i];
}
cout<<endl;
pthread_cond_signal(&buffer_cond);
pthread_mutex_unlock(&buffer_mutex);
return null;
}
void* thirdthreadfunc(void* proc) {
string a = "data sent";
pthread_mutex_lock(&buffer_mutex);
pthread_cond_wait(&buffer_cond, &buffer_mutex);
sleep(1);
cout<<"thread three"<<endl;
for(int i = 0;i<9;i++){
buffer[i] = a[i];
cout<<buffer[i];
}
cout<<endl;
pthread_cond_signal(&buffer_cond);
pthread_mutex_unlock(&buffer_mutex);
return null;
}
int main() {
pthread_t p_threadone, p_threadtwo, p_threadthree;;
pthread_attr_t attr;
pthread_attr_init(&attr);
for(int i = 0;i<100;i++){
buffer[i] = 'a';
}
//create threads
cout<<"creating threads"<<endl;
pthread_create(&p_threadone, &attr, firstthreadfunc, null);
pthread_create(&p_threadtwo, &attr, secondthreadfunc, null);
pthread_create(&p_threadthree, &attr, thirdthreadfunc, null);
//terminate threads
pthread_join(p_threadone,null);
pthread_join(p_threadtwo,null);
pthread_join(p_threadthree,null);
return 0;
}
Thanks WhozCraig and Tony, your answers resolved the issue. I understand what I was doing wrong.
First, where you're stuck. The following line in either thread2 or thread3 is the sticking point:
pthread_cond_wait(&buffer_cond, &buffer_mutex);
And by now you're asking, "Why?" Because your mistaking a condition variable as a state; not a signaling mechanism. Condition variables are intended to be used to signal interested waiters of change in state of something else: the predicate. You have none. Consider the following modified version of your code.
This uses two predicate values (I advise you stick with one per condvar until you become more comfortable with them; start simple), protecting them with the same mutex and signaling their change with the same condition variable. The important thing to note is that we don't wait on the condition variable until we know the predicate we're waiting for is not ready yet. And since we have the mutex locked, we can safely do check that predicate:
#include <iostream>
#include <string>
#include <unistd.h>
#include <pthread.h>
using namespace std;
const int NUM_THREADS = 3;
char buffer[100];
bool bDataReady = false;
bool bDataWaiting = false;
pthread_mutex_t buffer_mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t buffer_cond = PTHREAD_COND_INITIALIZER;
void* firstThreadFunc(void* proc)
{
string a = "Data Received";
pthread_mutex_lock(&buffer_mutex);
cout<<"ThreadOne"<<endl;
std::copy(a.begin(), a.end(), buffer);
buffer[a.size()] = 0;
cout << buffer << endl;
bDataReady = true;
pthread_cond_broadcast(&buffer_cond);
pthread_mutex_unlock(&buffer_mutex);
return NULL;
}
void* secondThreadFunc(void* proc)
{
string a = "Data Processed";
pthread_mutex_lock(&buffer_mutex);
while (!bDataReady)
pthread_cond_wait(&buffer_cond, &buffer_mutex);
cout<<"ThreadTwo"<<endl;
std::copy(a.begin(), a.end(), buffer);
buffer[a.size()] = 0;
cout << buffer << endl;
bDataReady = false;
bDataWaiting = true;
pthread_cond_broadcast(&buffer_cond);
pthread_mutex_unlock(&buffer_mutex);
return NULL;
}
void* thirdThreadFunc(void* proc)
{
string a = "Data Sent";
pthread_mutex_lock(&buffer_mutex);
while (!bDataWaiting)
pthread_cond_wait(&buffer_cond, &buffer_mutex);
cout<<"Thread Three"<<endl;
std::copy(a.begin(), a.end(), buffer);
buffer[a.size()] = 0;
cout << buffer << endl;
bDataWaiting = false;
pthread_cond_broadcast(&buffer_cond);
pthread_mutex_unlock(&buffer_mutex);
return NULL;
}
int main() {
pthread_t p_threadOne, p_threadTwo, p_threadThree;;
pthread_attr_t attr;
pthread_attr_init(&attr);
for(int i = 0;i<100;i++){
buffer[i] = 'a';
}
//create Threads
cout<<"creating threads"<<endl;
pthread_create(&p_threadOne, &attr, firstThreadFunc, NULL);
pthread_create(&p_threadTwo, &attr, secondThreadFunc, NULL);
pthread_create(&p_threadThree, &attr, thirdThreadFunc, NULL);
//terminate Threads
pthread_join(p_threadOne,NULL);
pthread_join(p_threadTwo,NULL);
pthread_join(p_threadThree,NULL);
return 0;
}
Output
creating threads
ThreadOne
Data Received
ThreadTwo
Data Processed
Thread Three
Data Sent