M2103-TP9-EXO-0-Corrigé

/**
 *
 * @file   partied_echec.cpp
 *
 * @author M. Laporte
 *
 * @date   06/06/2019
 *
 * @brief  M2103 Testt 2 partie d'échec
 *
 **/

#include <vector>
#include <string>
#include <iostream>

 using namespace std;

namespace
{
    class Piece;

    #define classdef typedef
    classdef vector <Piece *> VPiece;
    enum Couleur {KBlanc, KNoir};
    enum Piece_t {KAucun, KRoi, KReine, KFou, KCavalier, KTour, KPion};
    vector <string> vNom {"", "Roi", "Reine", "Fou",
                          "Cavalier", "Tour", "Pion"};

    class Case;
    class Echiquier;
    class Joueur;

    class Piece
    {
      protected :
        Couleur  myCouleur;
        Piece_t  myNom;
        Case   * myCase;
        Joueur * myJoueur;
      public :
        Piece (Piece_t nom, Couleur couleur)
              : myCouleur (couleur), myNom (nom) {}

        Couleur getCouleur (void) const { return myCouleur; }
        Piece_t getNom     (void) const { return myNom; }
        Case *  getCase    (void) const { return myCase; }
        void setJoueur (Joueur * joueur) { myJoueur = joueur; }
        void setCase   (Case * laCase)   { myCase = laCase; }

        virtual bool operator () (Case * laCase) { return false; }
        virtual ~Piece (void) {}

    }; // Piece

    class Pion : public Piece
    {
      public :
        Pion (Piece_t nom, Couleur couleur) : Piece (nom, couleur)
        {}

        virtual bool operator () (Case * laCase) { return true; }
        virtual ~Pion (void) {}

    }; // Pion

    class Roi : public Piece
    {
      public :
        Roi (Piece_t nom, Couleur couleur) : Piece (nom, couleur) {}

        virtual bool operator () (Case * laCase) { return false; }
        virtual ~Roi (void) {}

    }; // Roi

    class Reine : public Piece
    {
      public :
        Reine (Piece_t nom, Couleur couleur) : Piece (nom, couleur) {}

        virtual bool operator () (Case * laCase) { return false; }
        virtual ~Reine (void) {}

    }; // Reine

    class Fou : public Piece
    {
      public :
        Fou (Piece_t nom, Couleur couleur) : Piece (nom, couleur) {}

        virtual bool operator () (Case * laCase) { return false; }
        virtual ~Fou (void) {}

    }; // Fou

    class Cavalier : public Piece
    {
      public :
        Cavalier (Piece_t nom, Couleur couleur) : Piece (nom, couleur) {}

        virtual bool operator () (Case * laCase) { return false; }
        virtual ~Cavalier (void) {}

    }; // Cavalier

    class Tour : public Piece
    {
      public :
        Tour (Piece_t nom, Couleur couleur) : Piece (nom, couleur) {}

        virtual bool operator () (Case * laCase) { return false; }
        virtual ~Tour (void) {}

    }; // Tour

    class Case
    {
        unsigned myLigne;
        unsigned myColonne;
        Piece  * myPiece;
      public :
        Case (unsigned ligne = 0, unsigned colonne = 0,
              Piece * piece = nullptr)
            : myLigne (ligne), myColonne (colonne), myPiece (piece) {}
        unsigned getLigne   (void) const      { return myLigne; }
        unsigned getColonne (void) const      { return myColonne; }
        Piece *  getPiece   (void) const      { return myPiece; }

        void     setPiece   (Piece * piece)   { myPiece  = piece; }

    }; // Case
    class Echiquier
    {
        vector <vector <Case>> myPlateau;
        vector <Piece>         myPieces;
        void addPions (Couleur couleur, unsigned numLigne)
        {
            for (unsigned col (0); col < myPlateau [numLigne].size ();
                 ++col)
            //for (Case & laCase : myPlateau [numLigne])
            {
                myPieces.push_back (Pion (KPion, couleur));
                myPieces.back().setCase (& (myPlateau [numLigne][col]));
                myPlateau [numLigne][col].setPiece (& (myPieces.back ()));
            }
        }// addPions()

      public :
        Echiquier (void)
        {
            myPlateau.resize (8);
            for (unsigned li (0); li < 8; ++li)
            {
                myPlateau [li].resize (8);
                for (unsigned col (0); col < 8; ++col)
                {
                    myPlateau [li][col] = Case (li, col);
                }
            }
            myPieces.reserve (32);
            // placer les pions
            addPions (KBlanc, 6);
            addPions (KNoir,  1);

            // placer les reines
            myPieces.push_back        (Reine (KReine, KNoir));
            myPieces.back().setCase   (& (myPlateau [0][3]));
            myPlateau [0][3].setPiece (& (myPieces.back ()));
            myPieces.push_back        (Reine (KReine, KBlanc));
            myPieces.back().setCase   (& (myPlateau [7][3]));
            myPlateau [7][3].setPiece (& (myPieces.back ()));

            // placer les rois
            myPieces.push_back        (Roi (KRoi, KNoir));
            myPieces.back().setCase   (& (myPlateau [0][4]));
            myPlateau [0][4].setPiece (& (myPieces.back ()));
            myPieces.push_back        (Roi (KRoi, KBlanc));
            myPieces.back().setCase   (& (myPlateau [7][4]));
            myPlateau [7][4].setPiece (& (myPieces.back ()));

            // placer les fous
            myPieces.push_back        (Fou (KFou, KNoir));
            myPieces.back().setCase   (& (myPlateau [0][2]));
            myPlateau [0][2].setPiece (& (myPieces.back ()));
            myPieces.push_back        (Fou (KFou, KBlanc));
            myPieces.back().setCase   (& (myPlateau [7][2]));
            myPlateau [7][2].setPiece (& (myPieces.back ()));

            myPieces.push_back        (Fou (KFou, KNoir));
            myPieces.back().setCase   (& (myPlateau [0][5]));
            myPlateau [0][5].setPiece (& (myPieces.back ()));
            myPieces.push_back        (Fou (KFou, KBlanc));
            myPieces.back().setCase   (& (myPlateau [7][5]));
            myPlateau [7][5].setPiece (& (myPieces.back ()));

            // placer les cavaliers
            myPieces.push_back        (Cavalier (KCavalier, KNoir));
            myPieces.back().setCase   (& (myPlateau [0][1]));
            myPlateau [0][1].setPiece (& (myPieces.back ()));
            myPieces.push_back        (Cavalier (KCavalier, KBlanc));
            myPieces.back().setCase   (& (myPlateau [7][1]));
            myPlateau [7][1].setPiece (& (myPieces.back ()));

            myPieces.push_back        (Cavalier (KCavalier, KNoir));
            myPieces.back().setCase   (& (myPlateau [0][6]));
            myPlateau [0][6].setPiece (& (myPieces.back ()));
            myPieces.push_back        (Cavalier (KCavalier, KBlanc));
            myPieces.back().setCase   (& (myPlateau [7][6]));
            myPlateau [7][6].setPiece (& (myPieces.back ()));

            // placer les tours
            myPieces.push_back        (Tour (KTour, KNoir));
            myPieces.back().setCase   (& (myPlateau [0][0]));
            myPlateau [0][0].setPiece (& (myPieces.back ()));
            myPieces.push_back        (Tour (KTour, KBlanc));
            myPieces.back().setCase   (& (myPlateau [7][0]));
            myPlateau [7][0].setPiece (& (myPieces.back ()));

            myPieces.push_back        (Tour (KTour, KNoir));
            myPieces.back().setCase   (& (myPlateau [0][7]));
            myPlateau [0][7].setPiece (& (myPieces.back ()));
            myPieces.push_back        (Tour (KTour, KBlanc));
            myPieces.back().setCase   (& (myPlateau [7][7]));
            myPlateau [7][7].setPiece (& (myPieces.back ()));

        } // Echiquier()

        VPiece getPieces (const Couleur & couleur) const
        {
            vector <Piece *> v;
            v.reserve (16);
            unsigned cpt = 0;
            for (vector <Case> vCase : myPlateau)
                for (Case laCase : vCase)
                {
                    if (laCase.getPiece () != nullptr)
                    {						//&&
                        if (laCase.getPiece ()->getCouleur () == couleur)
                            v.push_back (laCase.getPiece ());
                    }
                }
            return v;

        } // getPieces()

        Case * getCase (unsigned i, unsigned j)
        { return &(myPlateau[i][j]); }

    }; // Echiquier
    
    class Joueur
    {
        string myNom;
        VPiece myPieces;
        Echiquier * myPlateau;
      public :
        Joueur (const string & nom, const VPiece &vPieces,
                 Echiquier * plateau)
               : myNom (nom), myPieces (vPieces), myPlateau (plateau)  {}

        Piece * choisirPiece (void)
        {
            for (unsigned i (0); i < myPieces.size (); ++i)
                cout << i << ' ' << vNom [myPieces [i]->getNom ()]
                     << myPieces [i]->getNom ()
                     << ' ' << myPieces [i]->getCase ()->getLigne ()
                     << ' ' << myPieces [i]->getCase ()->getColonne ()
                     << endl;
            cout << "Quelle piece voulez-vous jouer ?";
            unsigned piece;
            cin >> piece;
            return myPieces [piece];

        } // choisirPiece()

        void move (Case * laCase, Piece * piece)
        {
            piece->getCase()->setPiece (nullptr);
            piece->setCase (laCase);
            laCase->setPiece (piece);

        } // move()

        void jouer (Piece * piece)
        {
            unsigned ligne;
            unsigned colonne;
            do
            {
                cout << "Où voulez-vous jouer "
                     << vNom [piece->getNom ()] << " ? "
                     << "Ligne Colonne ? ";
                cin >> ligne >> colonne;
            } while ((*piece)(myPlateau->getCase (ligne, colonne)));
            move (myPlateau->getCase (ligne, colonne), piece);


        } // jouer()

    }; // Joueur

    class Partie
    {
        Echiquier * myEchiquier;
        vector <Joueur *> myJoueurs;
      public :
        Partie (Joueur * j1, Joueur * j2, Echiquier * echiquier)
               : myEchiquier (echiquier)
        {
            myJoueurs.reserve (2);
            myJoueurs.push_back (j1);
            myJoueurs.push_back (j2);

            bool aJ2 = false;

            /*    */
            while (true)
            {
                Piece * piece = myJoueurs [aJ2]->choisirPiece ();
                myJoueurs [aJ2]->jouer (piece);
                aJ2 = ! aJ2;
                break;
            }
            /*     */
        } // Partie()

    }; // Partie

}// namespace
int main (void)
{
    Echiquier plateau;
    Joueur joueur1 ("Alain", plateau.getPieces (KBlanc), & plateau);
    Joueur joueur2 ("Marc",  plateau.getPieces (KNoir),  & plateau);

    Partie unePartie (& joueur1, & joueur2, & plateau);

    return 12;

} // main()

M4104C-boost-Exo1-Corrigé

/**
 * @file   Concurrence.cxx
 *
 * @author D. Mathieu
 *         M. Laporte
 *
 * @date   17/02/2010
 *
 * @brief  Concurrence
 *
 * Acces protege par une section critique implementee par un lock_guard
 *
 */
#include <iostream>
#include <sstream>
#include <vector>

#include <boost/thread/thread.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/thread/locks.hpp>

using namespace std;
using namespace boost;

enum { KErrArg  = 253 };    // Erreur d'arguments de main()

typedef unsigned long long ULL_t;
typedef          long long  LL_t;

namespace
{
    volatile LL_t  a (0);
    ULL_t NbBoucles;
    mutex Mtx;

    class Incr
    {
      public :
        void operator () (void)
        {
            for (ULL_t i = 0; i < NbBoucles; ++i)
            {
                lock_guard <mutex> Lock (Mtx);
                ++a;
            }
        } // operator()()

    }; // Incr

    class Decr
    {
      public :
        void operator () (void)
        {
            for (ULL_t i = 0; i < NbBoucles; ++i)
            {
                lock_guard <mutex> Lock (Mtx);
                --a;
            }
        } // operator()()

    }; // Decr

} // namespace anonyme

int main (int argc, char * argv [])
{
    if (argc != 3)
    {
         cerr << "Usage : Concurrence <NbThreads> <NbBoucles>\n";
         return KErrArg;
    }
    unsigned NbThreads;
    {
         istringstream is (argv [1]);
         is >> NbThreads;
    }
    {
         istringstream is (argv [2]);
         is >> NbBoucles;
    }
    cout <<   "Nbre de threads : " << NbThreads
         << "\nNbre de boucles : " << NbBoucles << '\n';

    // vector <thread *> VThreads;
    thread_group threadGroup;

    for (unsigned i = NbThreads; i--; )
    {
        // VThreads.push_back (new thread (Incr));
        threadGroup.add_thread (new thread (Incr ()));
        // VThreads.push_back (new thread (Decr));
        threadGroup.add_thread (new thread (Decr ()));

    }
    // for (unsigned i = NbThreads * 2; i--; ) VThreads[i]->join ();
    threadGroup.join_all ();

    cout << "a = " << a << '\n';

    return 0;

} // main()





M4104C-boost-Exo2-Corrigé

/**
 *
 * @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()

M4104C-boost-Exo3-Corrigé

/**
 *
 * @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()