// ********************************************************************** // // Copyright (c) 2000 // Object Oriented Concepts, Inc. // Billerica, MA, USA // // All Rights Reserved // // ********************************************************************** #include #include #if defined(HAVE_STRSTREAM) # include #else # if defined(HAVE_STRSTREA_H) # include # else # include # endif #endif #ifdef HAVE_STD_IOSTREAM using namespace std; #endif // // This class ensures that the iostream class is only accessed by one // thread. This stops corruption of the output stream. // class MTCout : public JTCMonitor { public: void write(const char* buf) { JTCSynchronized sync(*this); cout << buf << endl; } }; // // Global instance of the MTCout object. // MTCout mtCout; // // This class returns a random number. // class Random : public JTCMonitor { public: int operator()() { JTCSynchronized sync(*this); return rand(); } }; // // Global instance of the random object. // Random genRandom; // // This class represents a chopstick. // class Chopstick : public JTCMonitor { }; // // We have N_DINERS diners, and N_DINERS chopsticks. // #define N_DINERS 5 Chopstick chopsticks[N_DINERS]; // // A room. // class Room : public JTCMonitor { int occupancy_; // Number of people in the room. int maxOccupancy_; // Maximum number of people allowed in the room. public: // // Constructor. // Room(int maxOccupancy) : occupancy_(0), maxOccupancy_(maxOccupancy) { } // // Add a person to the room. // void addPerson() { JTCSynchronized sync(*this); ++occupancy_; notifyAll(); } // // Remove a person from the room. // void removePerson() { JTCSynchronized sync(*this); --occupancy_; notifyAll(); } // // Wait for a place to become available. // void waitForPlace() { JTCSynchronized sync(*this); while(occupancy_ == maxOccupancy_) { try { wait(); } catch(const JTCInterruptedException&) { } } } // // Get the number of people in the room. // int numberPeople() { JTCSynchronized sync(*this); return occupancy_; } }; Room room(N_DINERS); class Philosopher; // // Array of philosopher threads. // bool phillies[N_DINERS]; // // This class represents a hungry philosopher. // class Philosopher : public JTCThread { int id_; // The id of the philosopher. public: // // Constructor. // Philosopher(int id) : id_(id) { } // // Mainline. Grab left chopstick, grab right chopstick. Eat food. // Ponder life for a while. Put down the chopsticks, and sleep for // a while. Repeat this cycle some random number of times. // Then exit the room. // virtual void run() { // // The variables l and r represent the index of the left and // right chopsticks around the table. // int l = id_; int r = l+1; if(r == N_DINERS) { r = 0; } if(l & 1) { int t = l; l = r; r = t; } char buf[1024]; ostrstream os(buf, sizeof(buf)); os << "Philosopher #" << id_ << " has entered the room." < 1) { nInQ = atoi(argv[1]); } // // Seed the random number generator. // srand(0); int i; // // Add N_DINERS to the room. // for(i =0; i < N_DINERS; ++i) { room.addPerson(); phillies[i] = true; JTCThreadHandle p = new Philosopher(i); p -> start(); } // // Repeat forever. // while (nInQ > 0 || nInQ == -1) { // // Wait for a place to open up in the room. // room.waitForPlace(); mtCout.write("main thread sleep."); JTCThread::sleep(3); mtCout.write("main thread wake."); // // Find the location of the philospher that left the room. // for(i =0; i < N_DINERS; ++i) if(!phillies[i]) break; // // Can't find the location? This is an internal error of // some sort. // if(i == N_DINERS) abort(); // // Create a new philosopher thread, add a person to the room. // room.addPerson(); phillies[i] = true; JTCThreadHandle p = new Philosopher(i); p -> start(); if (nInQ != -1) { --nInQ; } } } catch(const JTCException& e) { cout << "Exception: " << e.getMessage() << endl; return EXIT_FAILURE; } return EXIT_SUCCESS; }