/**
*
* @file BALMultiThreadsBoost.cpp
*
* @author D. onethieu, M. Laporte
*
* @date 19/10/2008
*
* @version 1.0
*
* @brief Boite a lettres generique
*
**/
#include <iostream>
#include <cstdlib> // srand(), rand()
#include <ctime> // time()
#include <boost/thread/thread.hpp>
#include <boost/thread/locks.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/thread/condition.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
//#include "nsUtil.h"
using namespace std;
using namespace boost;
using namespace boost::posix_time; // time_duration
//using namespace nsUtil;
namespace
{
typedef string CMessage;
mutex myMtxKeyBoard;
mutex myMtxScreen;
template <class Letter>
class LetterboxGen
{
condition_variable myCondVarProd;
condition_variable myCondVarConsum;
mutex myMtxCondVar;
Letter myLetter;
bool myIsEmpty;
public :
LetterboxGen (void) : myIsEmpty (true) {}
void push (const Letter & oneLetter, system_time & stamp)
{
{
unique_lock <mutex> oneLock (myMtxCondVar);
if (!myIsEmpty) myCondVarProd.wait (oneLock);
stamp = get_system_time();
myLetter = oneLetter;
myIsEmpty = false;
}
myCondVarConsum.notify_one();
} // push()
Letter pop (system_time & stamp)
{
Letter oneLetter;
{
unique_lock <mutex> oneLock (myMtxCondVar);
if (myIsEmpty) myCondVarConsum.wait (oneLock);
stamp = get_system_time();
oneLetter = myLetter;
myIsEmpty = true;
}
myCondVarProd.notify_one();
return oneLetter;
} // pop()
}; // LetterboxGen
typedef LetterboxGen <CMessage> LetterboxString;
LetterboxString theBox;
unsigned rand (unsigned min, unsigned max)
{
return std::rand () % (max - min) + min;
} // rand()
class Producer
{
static unsigned s_ID;
unsigned myID;
public :
Producer (void) : myID (++s_ID) {}
void operator() (void)
{
system_time stamp;
string oneLetter;
for ( ; ; )
{
{
lock_guard <mutex> oneLock (myMtxKeyBoard);
cin >> oneLetter;
}
if (cin.eof ()) break;
this_thread::sleep (seconds (rand (1, 5)));
theBox.push (oneLetter, stamp);
{
lock_guard <mutex> oneLock (myMtxScreen);
cout << stamp << " : Prod. " << myID
<< " a déposé : " << oneLetter << '\n';
}
this_thread::sleep (seconds (rand (1, 5)));
}
{
lock_guard <mutex> oneLock (myMtxScreen);
cout << "Producteur " << myID << " se termine\n";
}
} // operator ()
}; // Producer
class Consumer
{
static unsigned s_ID;
unsigned myID;
public :
Consumer (void) : myID (++s_ID) {}
void operator() (void)
{
system_time stamp;
string oneLetter;
for ( ; ; )
{
this_thread::sleep (seconds (rand (1, 5)));
oneLetter = theBox.pop (stamp);
{
lock_guard <mutex> oneLock (myMtxScreen);
cout << stamp << " : Cons. " << myID
<< " a retiré : " << oneLetter << '\n';
}
this_thread::sleep (seconds (rand (1, 5)));
}
} // operator ()
}; // Consumer
unsigned Producer ::s_ID (0);
unsigned Consumer::s_ID (0);
} // namespace
int main()
{
srand (time (nullptr));
unsigned NbConsumateurs = 3;
unsigned NbProducteurs = 2;
vector <thread *> VThreads;
for (unsigned i = NbProducteurs; i--; )
VThreads.push_back (new thread (Producer()));
for (unsigned i = NbConsumateurs; i--; )
VThreads.push_back (new thread (Consumer()));
for (unsigned i = NbProducteurs + NbConsumateurs; i--; )
VThreads[i]->join ();
return 0;
} // main()