/**
*
* @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 m_x, m_y;
}; // gotoxy()
std::ostream & operator << (std::ostream & os, const gotoxy & m);
// La fonction
//
//===============================================//
// //
void SleepChronogram ( //
unsigned Num, //
unsigned & Col, //
char Status, //
unsigned Duree, //
boost::mutex & Mutex, //
unsigned Decal = 10u, //
unsigned Periode = 1u //
) //
throw (std::ios_base::failure); //
// //
//===============================================//
//
// fait dormir le thread qui l'appelle pendant Duree 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
// Mutex : mutex POSIX utilise pour l'affichage
// Periode : periodicite de l'affichage (en secondes)
// Duree : 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).
// Col : 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) : m_x (x), m_y (y) {}
ostream & nsUtil::operator << (ostream & os, const gotoxy & m)
{
return os << "\033[" << m.m_y << ';' << m.m_x << 'H';
}
#undef GOTOXY
void nsUtil::SleepChronogram (unsigned Num,
unsigned & Col,
char Status,
unsigned Duree,
boost::mutex & ioMutex,
unsigned Decal /* = 10u */,
unsigned Periode /* = 1u */)
throw (std::ios_base::failure)
{
for (unsigned i = Duree; i--; )
{
{
lock_guard <mutex> Lock (ioMutex);
cout << gotoxy (Col++, Num + Decal) << Status << flush;
}
this_thread::sleep (seconds (Periode));
}
} // SleepChronogr()
/**
* @file RDV_NThreadsBoost_c.cpp
*
* @author D. Mathieu
* M. Laporte
*
* @date 08/10/2008
*
* @brief Rendez-vous de N threads par la fonction barrier()
*
* Rendez-vous de N threads par la fonction barrier()
*
*/
#include <iostream>
#include <sstream>
#include <vector>
#include <boost/thread/thread.hpp>
#include <boost/thread/locks.hpp>
#include <boost/thread/barrier.hpp>
//#include "SleepChronogram.h"
using namespace std;
using namespace boost;
using namespace nsUtil;
namespace
{
enum { KExcArg = 253 }; // Erreur d'arguments de main()
mutex io_Mtx;
barrier * pBarriere;
void RendezVous ()
{
pBarriere->wait();
} // RendezVous()
class CPassant
{
static unsigned s_ID;
unsigned m_ID;
unsigned m_DelaiAvant;
unsigned m_DelaiApres;
public :
CPassant (const CPassant & P)
: m_ID (P.m_ID),
m_DelaiAvant (P.m_DelaiAvant),
m_DelaiApres (P.m_DelaiApres) {}
CPassant (unsigned DelaiAvant, unsigned DelaiApres)
: m_ID (++s_ID),
m_DelaiAvant (DelaiAvant), m_DelaiApres (DelaiApres) {}
void operator () ()
{
unsigned Col (1);
SleepChronogram (m_ID, Col, 'A', m_DelaiAvant, io_Mtx);
RendezVous();
SleepChronogram (m_ID, Col, 'D', m_DelaiApres, io_Mtx);
SleepChronogram (m_ID, Col, 'X', 1, io_Mtx);
} // operator()
}; // CPassant
} // namespace
unsigned CPassant::s_ID (0);
int main (int argc, char * argv [])
{
if (argc != 1)
{
cerr << "Usage : RDV_NThreadsBoost\n";
return KExcArg;
}
unsigned NbThreads;
cin >> NbThreads;
pBarriere = new barrier (NbThreads);
vector <CPassant> VPassants;
VPassants.reserve (NbThreads);
for (unsigned DelaiAvant, DelaiApres, i (0); i < NbThreads; ++i)
{
cin >> DelaiAvant >> DelaiApres;
VPassants.push_back (CPassant (DelaiAvant, DelaiApres));
}
thread_group GrpThreads;
cout << clrscr << flush;
for (unsigned i = NbThreads; i--; )
GrpThreads.create_thread (VPassants [i]);
GrpThreads.join_all ();
cout << gotoxy (0, NbThreads + 12);
return 0;
} // main()