/**
*
* @file sleepChronogram.h
*
* @author M. Laporte, D. Mathieu
*
* @date 05/01/2007
*
* @version 2.0
*
* @brief SleepChronogr() affiche periodiquement un caractere
**/
#if !defined __SLEEP_CHRONOGR_H__
#define __SLEEP_CHRONOGR_H__
#include <iostream> // ios_base::failure
#include <string>
#include <boost/thread/thread.hpp>
#include <boost/thread/locks.hpp>
namespace nsUtil
{
// L'injection de la NTCTS
//
//=========================//
// //
extern std::string clrscr; //
// //
//=========================//
//
// vide l'ecran et positionne le curseur en haut a gauche
// La
//
//============//
// //
class gotoxy; //
// //
//============//
//
// est un injecteur qui positionne le curseur a l'ecran
// en position x et y :
//
// cout << gotoxy (10, 20) << ...
class gotoxy
{
public :
gotoxy (int x, int y);
friend std::ostream & operator << (std::ostream & os,
const gotoxy & m);
private :
int myx, myy;
}; // gotoxy()
std::ostream & operator << (std::ostream & os, const gotoxy & m);
// La fonction
//
//===============================================//
// //
void sleepChronogram ( //
unsigned num, //
unsigned & column, //
char status, //
unsigned oneDuration, //
boost::mutex & oneMutex, //
unsigned decal = 10u, //
unsigned period = 1u //
) //
throw (std::ios_base::failure); //
// //
//===============================================//
//
// fait dormir le thread qui l'appelle pendant oneDuration secondes au
// moyen de la fonction ::sleep().
//
// Elle est destinee a tracer des chronogrammes de threads pendant
// leur periode de sommeil, chronogrammes qui apparaissent comme
// dans l'exemple ci-dessous :
//
// ------------ Haut de l'ecran ----------------------
// ^
// |
// |
// decal
// |
// |
// v
// AAADDDDD
// AAAADDDDD
// AAAAADDX
//
//------------- Bas de l'ecran -----------------------
//
// status : caractere affiche en exclusion mutuelle.
// Il est sense representer l'etat courant du thread
// oneMutex : mutex POSIX utilise pour l'affichage
// period : periodicite de l'affichage (en secondes)
// oneDuration : duree totale de l'affichage (= du sommeil du thread)
// decal : nombre de lignes vierges en haut de l'ecran
// num : numero de la ligne d'affichage sur laquelle est affiche
// le caractere status.
// Le curseur apparait donc a la ligne (decal + num).
// num est en general le numero du thread (e partir de 0).
// column : en entree : colonne du premier affichage du caractere
// status
// : en sortie : position du curseur en fin d'affichage
//
// La fonction Sleep () est susceptible de lever deux exceptions
// - std::ios_base::failure lors de l'injection du caractere
// - nsUtil::CExcFct lors du (de)-verrouillage du mutex
// (voir CException.h)
} // namespace nsUtil
#endif /* __SLEEP_CHRONOGR_H__ */
/**
*
* @file sleepChronogram.cpp
*
* @author M. Laporte, D. Mathieu
*
* @date 05/01/2007
*
* @version 2.0
*
* @brief SleepChronogr() affiche periodiquement un caractere
**/
#include <iostream>
#include <unistd.h> // sleep()
//#include "sleepChronogram.h"
using namespace std;
using namespace boost;
using namespace boost::posix_time;
string nsUtil::clrscr ("\033[2J"); // Clear screen
#define GOTOXY nsUtil::gotoxy
GOTOXY::gotoxy (int x, int y) : myx (x), myy (y) {}
ostream & nsUtil::operator << (ostream & os, const gotoxy & m)
{
return os << "\033[" << m.myy << ';' << m.myx << 'H';
}
#undef GOTOXY
void nsUtil::sleepChronogram (unsigned num,
unsigned & column,
char status,
unsigned oneDuration,
boost::mutex & ioMutex,
unsigned decal /* = 10u */,
unsigned period /* = 1u */)
throw (std::ios_base::failure)
{
for (unsigned i = oneDuration; i--; )
{
{
lock_guard <mutex> oneLock (ioMutex);
cout << gotoxy (column++, num + decal) << status << flush;
}
this_thread::sleep (seconds (period));
}
} // SleepChronogram()
/**
* @file PoscineThreadsBoost.cpp
*
* @author D. Mathieu
* M. Laporte
*
* @date 23/09/2008
*
* @brief Simulation du fonctionnement d'une piscine
*
* Simulation du fonctionnement d'une piscine
* Gestion de plusieurs ressources de natures differentes
*/
#include <iostream>
#include <vector>
#include <boost/thread/thread.hpp>
#include <boost/thread/locks.hpp>
#include <boost/thread/condition.hpp>
//#include "CstCodErr.h"
//#include "SleepChronogram.h"
using namespace std;
using namespace boost;
using namespace nsUtil; // KExcArg
namespace
{
enum { KExcArg = 253 }; // Erreur d'arguments de main()
mutex io_Mtx;
mutex mtxCond;
condition_variable condition;
unsigned nbBaskets;
unsigned nbCubicles;
void beginUndressing (void)
{
unique_lock <mutex> oneLock (mtxCond);
while (nbCubicles == 0 || nbBaskets == 0) condition.wait (oneLock);
--nbBaskets;
--nbCubicles;
} // beginUndressing()
void endUndressing (void)
{
unique_lock <mutex> oneLock (mtxCond);
++nbCubicles;
condition.notify_all ();
} // endUndressing()
void beginDressingAgain (void)
{
unique_lock <mutex> oneLock (mtxCond);
while (nbCubicles == 0) condition.wait (oneLock);
--nbCubicles;
} // beginDressingAgain()
void endDressingAgain (void)
{
unique_lock <mutex> oneLock (mtxCond);
++nbCubicles;
++nbBaskets;
condition.notify_all ();
} // endDressingAgain()
class Bather
{
static unsigned s_ID;
unsigned myID;
unsigned myArrivalDuration;
unsigned myUndressingDuration;
unsigned myBathDuration;
unsigned myDressingAgainDuration;
unsigned myEndingDuration;
public :
Bather (unsigned arrivalDuration,
unsigned undressingDuration,
unsigned bathDuration,
unsigned dressingAgainDuration,
unsigned endingDuration)
: myID (++s_ID),
myArrivalDuration (arrivalDuration),
myUndressingDuration (undressingDuration),
myBathDuration (bathDuration),
myDressingAgainDuration (dressingAgainDuration),
myEndingDuration (endingDuration) {}
void operator ()()
{
unsigned Col (1);
sleepChronogram (myID, Col, 'A', myArrivalDuration,
io_Mtx);
beginUndressing();
sleepChronogram (myID, Col, 'D', myDressingAgainDuration, io_Mtx);
endUndressing ();
sleepChronogram (myID, Col, 'B', myBathDuration, io_Mtx);
beginDressingAgain ();
sleepChronogram (myID, Col, 'R', myDressingAgainDuration, io_Mtx);
endDressingAgain ();
sleepChronogram (myID, Col, 'Q', myEndingDuration, io_Mtx);
sleepChronogram (myID, Col, 'X', 1, io_Mtx);
} // operator()
}; // Bather
} // namespace
unsigned Bather::s_ID (0);
int main (int argc, char * argv [])
{
if (argc != 1)
{
cerr << "Usage : PiscineThreadsBoost\n";
return KExcArg;
}
unsigned nbThreads;
cin >> nbBaskets >> nbCubicles >> nbThreads;
cout << clrscr << flush;
vector <Bather> vBathers;
vBathers.reserve (nbThreads);
for (unsigned arrivalDuration, undressingDuration, bathDuration,
dressingAgainDuration, endingDuration, i (0); i < nbThreads; ++i)
{
cin >> arrivalDuration >> undressingDuration >> bathDuration
>> dressingAgainDuration >> endingDuration;
vBathers.push_back (
Bather (arrivalDuration, undressingDuration,
bathDuration, dressingAgainDuration, endingDuration));
}
thread_group grpThreads;
cout << clrscr << flush;
for (unsigned i = nbThreads; i--; )
grpThreads.create_thread (vBathers [i]);
grpThreads.join_all ();
cout << gotoxy (0, nbThreads + 12);
return 0;
} // main()