//: C11:DiningPhilosophers.h // Classes for Dining Philosophers. #ifndef DININGPHILOSOPHERS_H #define DININGPHILOSOPHERS_H #include <string> #include <iostream> #include <cstdlib> #include "zthread/Condition.h" #include "zthread/Guard.h" #include "zthread/Mutex.h" #include "zthread/Thread.h" #include "Display.h" class Chopstick { ZThread::Mutex lock; ZThread::Condition notTaken; bool taken; public: Chopstick() : notTaken(lock), taken(false) {} void take() { ZThread::Guard<ZThread::Mutex> g(lock); while(taken) notTaken.wait(); taken = true; } void drop() { ZThread::Guard<ZThread::Mutex> g(lock); taken = false; notTaken.signal(); } }; class Philosopher : public ZThread::Runnable { Chopstick& left; Chopstick& right; int id; int ponderFactor; ZThread::CountedPtr<Display> display; int randSleepTime() { if(ponderFactor == 0) return 0; return rand()/(RAND_MAX/ponderFactor) * 250; } void output(std::string s) { std::ostringstream os; os << *this << " " << s << std::endl; display->output(os); } public: Philosopher(Chopstick& l, Chopstick& r, ZThread::CountedPtr<Display>& disp, int ident,int ponder) : left(l), right(r), id(ident), ponderFactor(ponder), display(disp) {} virtual void run() { try { while(!ZThread::Thread::interrupted()) { output("thinking"); ZThread::Thread::sleep(randSleepTime()); // Hungry output("grabbing right"); right.take(); output("grabbing left"); left.take(); output("eating"); ZThread::Thread::sleep(randSleepTime()); right.drop(); left.drop(); } } catch(ZThread::Synchronization_Exception& e) { output(e.what()); } } friend std::ostream& operator<<(std::ostream& os, const Philosopher& p) { return os << "Philosopher " << p.id; } }; #endif // DININGPHILOSOPHERS_H ///:~
Listado 10.35. C11/DiningPhilosophers.h
//: C11:DeadlockingDiningPhilosophers.cpp {RunByHand} // Dining Philosophers with Deadlock. //{L} ZThread #include <ctime> #include "DiningPhilosophers.h" #include "zthread/ThreadedExecutor.h" using namespace ZThread; using namespace std; int main(int argc, char* argv[]) { srand(time(0)); // Seed the random number generator int ponder = argc > 1 ? atoi(argv[1]) : 5; cout << "Press <ENTER> to quit" << endl; enum { SZ = 5 }; try { CountedPtr<Display> d(new Display); ThreadedExecutor executor; Chopstick c[SZ]; for(int i = 0; i < SZ; i++) { executor.execute( new Philosopher(c[i], c[(i+1) % SZ], d, i,ponder)); } cin.get(); executor.interrupt(); executor.wait(); } catch(Synchronization_Exception& e) { cerr << e.what() << endl; } } ///:~
Listado 10.36. C11/DeadlockingDiningPhilosophers.cpp
//: C11:FixedDiningPhilosophers.cpp {RunByHand} // Dining Philosophers without Deadlock. //{L} ZThread #include <ctime> #include "DiningPhilosophers.h" #include "zthread/ThreadedExecutor.h" using namespace ZThread; using namespace std; int main(int argc, char* argv[]) { srand(time(0)); // Seed the random number generator int ponder = argc > 1 ? atoi(argv[1]) : 5; cout << "Press <ENTER> to quit" << endl; enum { SZ = 5 }; try { CountedPtr<Display> d(new Display); ThreadedExecutor executor; Chopstick c[SZ]; for(int i = 0; i < SZ; i++) { if(i < (SZ-1)) executor.execute( new Philosopher(c[i], c[i + 1], d, i, ponder)); else executor.execute( new Philosopher(c[0], c[i], d, i, ponder)); } cin.get(); executor.interrupt(); executor.wait(); } catch(Synchronization_Exception& e) { cerr << e.what() << endl; } } ///:~
Listado 10.37. C11/FixedDiningPhilosophers.cpp