#include #include #include #include #include #include using namespace std ; std::mutex mutexObject1 ; std::mutex mutexObject2 ; std::mutex mtxG ; // mutex for critical section mutex mtxW ; class buffer { public: int* holder ; int counter ; int length_of_buffer ; std::condition_variable cv1 ; std::condition_variable cv2 ; buffer( int buffersize ) { cout << "Buffer costructor with size:" + buffersize << endl ; counter = -1 ; //counter is empty length_of_buffer = buffersize ; //if counter == length_of_buffer-1 means full holder = new int[buffersize] ; } int read( int threadId ) { int retValue = 0 ; //cout << "Start of bufferObject:read() 1: " << endl ; //lockObject1.lock(); std::unique_lock lockObject1(mutexObject1) ; //cout << "Start of bufferObject:read() 2: " << endl ; try { //check if empty while ( counter == -1 ) { cout << "bufferObject:read(): " << " Waiting for something to be written. threadId :" << threadId << " \r\n" ; cv1.wait( lockObject1 ); } //Need to protect this section mtxG.lock() ; int ret ; retValue = holder[counter] ; counter-- ; mtxG.unlock() ; //if ( counter == -1 ) // ready1 = false ; cout <<"Read value:" << retValue << " by thread:" << threadId << " counter" << counter << "\r\n" ; //lockObject2.unlock(); cv2.notify_one(); } catch(exception except ) { cout << "except.toString()" << endl ; } return retValue ; } //-------------------------------------------------------------------------------------- void write( int val1 , int threadId) { std::unique_lock lockObject2( mutexObject2 ) ; try { //check if full while ( counter == (length_of_buffer-1) ) { cout << "bufferObject:write(): Buffer full...Waiting to be read.:" << "Thread.currentThread() threadId :" << threadId << "\r\n" ; //cv2.wait(lockObject2, []{ return ready2; }); cv2.wait( lockObject2 ); } mtxG.lock() ; counter++ ; holder[counter] = val1 ; mtxG.unlock() ; cout <<"Adding value:" << val1 << " by thread:" << threadId << " Thread.currentThread().getName() counter:" << counter << endl ; cv1.notify_one(); lockObject2.unlock() ; } catch( exception e ) { cout << e.what() << endl ; } } } ; //----------------------------------------------------------- class writer { public: buffer& bufferObject ; int threadId ; int interval ; static int value ; writer( buffer& bufferObjectP, int intervalP , int threadIdP ) : bufferObject ( bufferObjectP ), threadId( threadIdP ) { interval = intervalP ; } void run() { try { while ( true ) { mtxW.lock() ; bufferObject.write( value , threadId ) ; value++ ; mtxW.unlock() ; sleep( interval ) ; } } catch( exception e ) { cout << "e.toString()" << endl ; } } } ; int writer::value = 1; class reader { public: buffer& bufferObject ; int interval ; int threadId ; reader( buffer& bufferObjectP, int intervalP, int threadIdP ) : bufferObject ( bufferObjectP ) , threadId( threadIdP ) { interval = intervalP ; } void run() { try { int value ; while ( true ) { value = bufferObject.read( threadId ) ; sleep( interval ) ; } } catch( exception e ) { cout << "read e.toString()" << endl ; } } }; //---------------------------------------------------- int main() { buffer bufferObject( 2 ) ; writer writerObject( bufferObject , 10 , 1 ) ; writer writerObject1( bufferObject , 3 , 2 ) ; reader readerObject( bufferObject , 5 , 1 ) ; reader readerObject1( bufferObject , 5 , 2 ) ; std::thread worker1 ( &writer::run, &writerObject ); std::thread worker4 ( &writer::run, &writerObject1 ); std::thread worker2 ( &reader::run, &readerObject ); std::thread worker3 ( &reader::run, &readerObject1 ); worker1.join() ; worker2.join() ; worker3.join() ; worker4.join() ; return 0 ; }