/**
*
* @file IterArbreThreadsBoost.cpp
*
* @author D. onethieu
*
* @date 21/10/2008
*
* @version 1.0
*
* @brief Iterateur a travers un arbre de recherche
*
**/
#include <iostream>
#include <boost/thread/thread.hpp>
#include <boost/thread/locks.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/thread/condition.hpp>
#include <boost/tr1/functional.hpp> // ou <functional> : bind()
using namespace std;
using namespace boost;
using namespace boost::posix_time; // time_duration
namespace
{
template <class Letter>
class MailboxGen
{
condition_variable myCondVarProd;
condition_variable myCondVarConsum;
mutex myMtxCondVar;
Letter myLetter;
bool myIsEmpty;
public :
MailboxGen (void) : myIsEmpty (true) {}
void push (const Letter & oneLetter)
{
{
unique_lock <mutex> oneLock (myMtxCondVar);
if (!myIsEmpty) myCondVarProd.wait (oneLock);
myLetter = oneLetter;
myIsEmpty = false;
}
myCondVarConsum.notify_one();
} // push()
Letter pop (void)
{
Letter oneLetter;
{
unique_lock <mutex> oneLock (myMtxCondVar);
if (myIsEmpty) myCondVarConsum.wait (oneLock);
oneLetter = myLetter;
myIsEmpty = true;
}
myCondVarProd.notify_one();
return oneLetter;
} // pop()
}; // MailboxGen
typedef MailboxGen <int> MailboxInt;
class Node;
class SearchTree;
class IterTree;
typedef Node * pNode_t;
class Node
{
int myValue;
pNode_t myLeftSon;
pNode_t myRightSon;
public :
pNode_t getLeftSon (void) const { return myLeftSon; }
pNode_t getRightSon (void) const { return myRightSon; }
void setLeftSon (pNode_t LeftSon) { myLeftSon = LeftSon; }
void setRightSon (pNode_t RightSon) { myRightSon = RightSon; }
Node (int value, pNode_t LeftSon = 0, pNode_t RightSon = 0)
: myValue (value), myLeftSon (LeftSon), myRightSon (RightSon) {}
int getValue (void) const { return myValue; }
}; // Node
class SearchTree
{
friend class IterTree;
pNode_t myRoot;
pNode_t addNode (int value, pNode_t root)
{
if (! root) return new Node (value);
if (value < root->getValue())
root->setLeftSon (addNode (value, root->getLeftSon()));
else
root->setRightSon (addNode (value, root->getRightSon()));
return root;
} // addNode()
public :
SearchTree (void) : myRoot (0) {}
void addNode (int value)
{
myRoot = addNode (value, myRoot);
} // addNode()
}; // SearchTree
class IterTree
{
MailboxGen <pNode_t> myMailbox;
SearchTree * myPTree;
void travel (pNode_t root)
{
if (!root) return;
travel (root->getLeftSon());
myMailbox.push (root);
travel (root->getRightSon());
} // travel()
void travel ()
{
travel (myPTree->myRoot);
myMailbox.push (0);
} // travel()
static void travelThr (IterTree * pIter)
{
cout << "\nDebut du parcours\n";
pIter->travel ();
cout << "\nFin du parcours\n";
} // travelThr()
public :
IterTree (SearchTree & tree)
: myPTree (& tree)
{
new thread (bind (travelThr, this));
} // IterTree()
pNode_t getNext (void)
{
return myMailbox.pop();
} // getNext()
}; // IterTree
SearchTree oneTree;
class Reader
{
static unsigned s_ID;
unsigned myID;
public :
Reader (void) : myID (++s_ID) {}
void operator () (void)
{
cout << "\nDebut du lecteur " << myID << '\n';
IterTree Iter (oneTree);
for (pNode_t Ptr; (Ptr = Iter.getNext()); )
{
cout << "Valeur lue par lecteur " << myID << " : "
<< Ptr->getValue() << '\n';
this_thread::sleep (seconds (1));
}
cout << "\nFin du lecteur " << myID << '\n';
} // operator()
}; // Reader
unsigned Reader::s_ID = 0;
} // namespace
int main(void)
{
int Tab [10] = { 1, 5, 3, 6, 7, 3, 4, 11, 9, 2};
for (unsigned i (0); i < 10; ++i) oneTree.addNode (Tab [i]);
thread_group groupThreads;
groupThreads.create_thread (Reader ());
this_thread::sleep (seconds (2));
groupThreads.create_thread (Reader ());
groupThreads.join_all ();
return 0;
} // main()