// ********************************************************************** // // Copyright (c) 2000 // Object Oriented Concepts, Inc. // Billerica, MA, USA // // All Rights Reserved // // ********************************************************************** #include #include #ifdef HAVE_STD_IOSTREAM using namespace std; #endif // // This example is a port of the CubbyHole example in the java tutorial. // See: http://java.sun.com/tutorial. // // This class acts as a cubby hole for producers and consumers. // A producer may not put another item in the cubby until a consumer // has retrieved the item. A consumer may not retrieve an item // until a producer has placed a new item in the hole. // class CubbyHole { bool available_; // Item available? int value_; // If so, what is the value of the item? int ref_; // Number of times the cubby hole is referenced. JTCMonitor mon_; // Associated monitor. public: // // Constructor. // CubbyHole() : available_(false), ref_(0) { } // // Increment reference count. // void reference() { ++ref_; } // // Decrement reference count. Delete the cubby if the reference // count drops to zero. // void dereference() { if(--ref_ == 0) { delete this; } } // // Place a new item in the hole. If the hole is currently // occupied, then block until the hole is empty. // void put(int v, int client) { JTCSynchronized sync(mon_); // // Loop while the hole is filled. // while(available_) { // // Wait to be notified. The monitor is notified when // the hole is filled, or emptied. // try { mon_.wait(); } catch(const JTCInterruptedException&) { } } // // The hole is now filled, with associated value. // Wake any waiting consumers. // available_ = true; value_ = v; mon_.notifyAll(); // // We put this display in here to avoid problems with // corrupting the output stream. // cout << "Producer #" << client << " put: " << value_ << endl; } // // Retrieve an element store in the cubby hole. If no element // is available for retrieval then wait. // int get(int client) { JTCSynchronized sync(mon_); // // While no element is available for retrieval wait. // while(!available_) { try { mon_.wait(); } catch(const JTCInterruptedException&) { } } // // Retrieve the element. Mark the state as "no element available". // Notify any waiting producers. // available_ = false; mon_.notifyAll(); // // Display the value while the monitor is still locked, since // this will prevent corruption of the output stream. // cout << "Consumer #" << client << " get: " << value_ << endl; return value_; } }; // // This class represents a consumer thread. This class is responsible // for retrieving elements from the cubby hole. // class Consumer : public JTCThread { CubbyHole* cubby_; // Pointer to the cubby hole. int number_; // The client number, for debugging. public: // // Constructor. // Consumer(CubbyHole* c, int which) : JTCThread("consumer"), cubby_(c), number_(which) { cubby_ -> reference(); } // // Destructor. // virtual ~Consumer() { cubby_ -> dereference(); } // // This method is called when start is invoked on the thread. // virtual void run() { // // Retrieve 10 numbers from the cubby hole. // for(int i = 0; i < 10; ++i) { cubby_ -> get(number_); } } }; // // This class represents the producer thread. This thread places objects // in the cubbyhole for a consumer to retrieve. // class Producer : public JTCThread { CubbyHole* cubby_; // The cubby hole object. int number_; // The client number, for debugging. public: // // Constructor. // Producer(CubbyHole* c, int which) : JTCThread("producer"), cubby_(c), number_(which) { cubby_ -> reference(); } // // Destructor. // virtual ~Producer() { cubby_ -> dereference(); } // // This method represents the main loop for this thread. // It places 10 numbers in the cubby hole. // virtual void run() { for(int i = 0; i < 10; ++i) { cubby_ -> put(i, number_); } } }; int main(int argc, char** argv) { try { // // A user of the JTC library must create an instance of this // class to initialize the library. // JTCInitialize bootJTC(argc, argv); // // Create an instance of the CubbyHole class. // CubbyHole* c = new CubbyHole; // // Create the producer and the consumer. // JTCThreadHandle producer = new Producer(c, 0); JTCThreadHandle consumer = new Consumer(c, 1); // // Start the threads. // producer -> start(); consumer -> start(); // // The instance of the JTCInitialize class will ensure that // this block is not exited until all threads terminate. // } catch(const JTCException& e) { cerr << "JTCException: " << e.getMessage() << endl; return EXIT_FAILURE; } return EXIT_SUCCESS; }