Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members  

panda/src/express/test_diners.cxx

Go to the documentation of this file.
00001 // Filename: test_diners.cxx
00002 // Created by:  cary (16Sep98)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
00008 //
00009 // All use of this software is subject to the terms of the Panda 3d
00010 // Software license.  You should have received a copy of this license
00011 // along with this source code; you will also find a current copy of
00012 // the license at http://www.panda3d.org/license.txt .
00013 //
00014 // To contact the maintainers of this program write to
00015 // panda3d@yahoogroups.com .
00016 //
00017 ////////////////////////////////////////////////////////////////////
00018 
00019 // A solution to the famous dining philosophers, implemented using the
00020 // threading abstraction.  This program exercises thread creation and
00021 // destruction, mutexes, and condition variables.
00022 
00023 #include "pandabase.h"
00024 #include "thread.h"
00025 #include "conditionVar.h"
00026 #include "mutexHolder.h"
00027 #include "pointerTo.h"
00028 
00029 #ifdef WIN32_VC
00030 static int last_rand = 0;
00031 #endif /* __WIN32__ */
00032 
00033 Mutex rand_mutex;
00034 
00035 static double random_f(double max)
00036 {
00037    MutexHolder l(rand_mutex);
00038    int i = rand();
00039 #ifdef WIN32_VC
00040    last_rand = i;
00041 #endif /* __WIN32__ */
00042    return max * (double)i / (double)RAND_MAX;
00043 }
00044 
00045 Mutex print_mutex;
00046 
00047 #define PRINTMSG(x) { MutexHolder l(print_mutex); x; }
00048 
00049 // n philosophers sharing n chopsticks.  Philosophers are poor folk and can't
00050 // afford luxuries like 2 chopsticks per person.
00051 #define N_DINERS 5
00052 
00053 Mutex chopsticks[N_DINERS];
00054 
00055 // At most n philosophers are allowed into the room, others would have to
00056 // wait at the door.  This restriction demonstrates the use of condition
00057 // variables.
00058 
00059 Mutex room_mutex;
00060 
00061 ConditionVar room_condition(room_mutex);
00062 int room_occupancy = 0;
00063 
00064 class philosopher;
00065 PT(philosopher) phils[N_DINERS];
00066 
00067 class philosopher : public Thread {
00068    private:
00069      int _id;
00070      void thread_main() {
00071 #ifdef WIN32_VC
00072          rand_mutex.lock();
00073          srand(last_rand);
00074          rand_mutex.release();
00075 #endif /* __WIN32__ */
00076          int l = _id;
00077          int r = l+1;
00078          if (r == N_DINERS)
00079             r = 0;
00080          if (l & 1) {
00081             int t = l;
00082             l = r;
00083             r = t;
00084          }
00085          PRINTMSG(cerr << "Philosopher #" << _id << " has entered the room."
00086                   << endl);
00087          int count = (int)random_f(10.0) + 1;
00088          while (--count) {
00089             chopsticks[l].lock();
00090             chopsticks[r].lock();
00091             PRINTMSG(cerr << "Philosopher #" << _id
00092                      << " is eating spaghetti now." << endl);
00093             Thread::sleep(random_f(3.0));
00094             chopsticks[l].release();
00095             chopsticks[r].release();
00096             PRINTMSG(cerr << "Philosopher #" << _id
00097                      << " is pondering about life." << endl);
00098             Thread::sleep(random_f(3.0));
00099          }
00100          room_mutex.lock();
00101          --room_occupancy;
00102          phils[_id] = (philosopher*)0L;
00103          room_condition.signal();
00104          room_mutex.release();
00105          PRINTMSG(cerr << "Philosopher #" << _id << " has left the room ("
00106                   << room_occupancy << " left)." << endl);
00107       }
00108 
00109       inline void* make_arg(const int i) { return (void*)new int(i); }
00110    public:
00111       philosopher(const int id) : Thread("philosopher") {
00112         _id = id;
00113       }
00114 };
00115 
00116 int main(int, char**)
00117 {
00118    int i;
00119    room_mutex.lock();
00120    for (i=0; i<N_DINERS; ++i) {
00121       phils[i] = new philosopher(i);
00122       phils[i]->start(TP_normal, false, false);
00123    }
00124    room_occupancy = N_DINERS;
00125    while (1) {
00126       while (room_occupancy == N_DINERS) {
00127          PRINTMSG(cerr << "main thread about to block " << room_occupancy
00128                   << endl);
00129          room_condition.wait();
00130       }
00131       // hmm.. someone left the room.
00132       room_mutex.release();
00133       // sleep for a while and then create a new philosopher
00134       PRINTMSG(cerr << "main thread sleep" << endl);
00135       Thread::sleep(2.0);
00136       PRINTMSG(cerr << "main thread wake up" << endl);
00137       room_mutex.lock();
00138       for (i=0; i<N_DINERS; ++i)
00139          if (phils[i] == (philosopher*)0L)
00140             break;
00141       if (i == N_DINERS) {
00142          PRINTMSG(cerr
00143                   << "Contrary to what I was tolk, no one has left the room!!!"
00144                   << endl);
00145          PRINTMSG(cerr << "I give up!" << endl);
00146          Thread::prepare_for_exit();
00147          exit(1);
00148       }
00149       phils[i] = new philosopher(i);
00150       ++room_occupancy;
00151    }
00152 }

Generated on Fri May 2 00:38:36 2003 for Panda by doxygen1.3