t_auto_synch.cpp

Go to the documentation of this file.
00001 /*****************************************************************************\
00002 *                                                                             *
00003 *  Name   : test_auto_synch                                                   *
00004 *  Author : Chris Koeritz                                                     *
00005 *                                                                             *
00006 *******************************************************************************
00007 * Copyright (c) 1998-$now By Author.  This program is free software; you can  *
00008 * redistribute it and/or modify it under the terms of the GNU General Public  *
00009 * License as published by the Free Software Foundation; either version 2 of   *
00010 * the License or (at your option) any later version.  This is online at:      *
00011 *     http://www.fsf.org/copyleft/gpl.html                                    *
00012 * Please send any updates to: fred@gruntose.com                               *
00013 \*****************************************************************************/
00014 
00015 #include <basis/chaos.h>
00016 #include <basis/guards.h>
00017 #include <basis/istring.h>
00018 #include <basis/mutex.h>
00019 #include <data_struct/amorph.cpp>
00020 #include <mechanisms/ithread.h>
00021 #include <mechanisms/safe_roller.h>
00022 #include <mechanisms/time_stamp.h>
00023 #include <loggers/file_logger.h>
00024 #include <opsystem/path_configuration.h>
00025 #include <data_struct/static_memory_gremlin.h>
00026 
00027 #ifdef __WIN32__
00028   #include <process.h>
00029 #endif
00030 
00031 HOOPLE_STARTUP_CODE;
00032 
00033 const int DEFAULT_FISH = 64;
00034   // the number of threads, by default.
00035 
00036 const int DEFAULT_RUN_TIME = 142 * SECOND_ms;
00037   // the length of time to run the program.
00038 
00039 int concurrent_biters = 0;
00040   // the number of threads that are currently active.
00041 
00042 int grab_lock = 0;
00043   // this is upped whenever a fish obtains access to the mutex.
00044 
00045 mutex *guard;
00046   // the guard ensures that the grab lock isn't molested by two fish at
00047   // once... hopefully.
00048 
00049 //hmmm: this should use a safe chaos object.
00050 
00051 const istring LOGFILE_NAME = path_configuration::make_logfile_name
00052     ("t_auto_synch.log");
00053   // where our debugging output goes by default.
00054 
00055 #define LOG(to_print) log.log(timestamp(true) + istring(to_print))
00056   // our macro for logging with a timestamp.
00057 
00058 chaos rando;
00059 
00060 class piranha : public ithread
00061 {
00062 public:
00063   piranha() : ithread(0), log(LOGFILE_NAME)
00064   {
00065     safe_add(concurrent_biters, 1);
00066 LOG(istring(istring::SPRINTF, "there are %d biters.", concurrent_biters));
00067   }
00068 
00069   ~piranha() { safe_add(concurrent_biters, -1); }
00070 
00071   void perform_activity(void *formal(data)) {
00072     auto_synchronizer l(*guard);
00073 
00074 LOG("locked guard!");
00075     safe_add(grab_lock, 1);
00076     if (grab_lock > 1)
00077       deadly_error("auto_synch test", "piranha", "grab lock was already active");
00078 
00079     portable::sleep_ms(rando.inclusive(20, 140));
00080 
00081     safe_add(grab_lock, -1);
00082 
00083 LOG("unlocking guard!");
00084   }
00085 
00086 private:
00087   file_logger log;
00088 };
00089 
00090 class barracuda : public ithread
00091 {
00092 public:
00093   barracuda() : ithread(0), log(LOGFILE_NAME) {
00094     safe_add(concurrent_biters, 1);
00095 LOG(istring(istring::SPRINTF, "there are %d biters.", concurrent_biters));
00096   }
00097 
00098   ~barracuda() { safe_add(concurrent_biters, -1); }
00099 
00100   void perform_activity(void *formal(data)) {
00101     auto_synchronizer l(*guard);
00102 
00103 LOG("locked guard!");
00104     safe_add(grab_lock, 1);
00105     if (grab_lock > 1)
00106       deadly_error("auto_synch test", "barracuda", "grab lock was already active");
00107 
00108     portable::sleep_ms(rando.inclusive(20, 140));
00109 //do something different?
00110   
00111     safe_add(grab_lock, -1);
00112 
00113 LOG("unlocking guard!");
00114   }
00115 
00116 private:
00117   file_logger log;
00118 };
00119 
00120 int main(int formal(argc), char *formal(argv)[])
00121 {
00122   file_logger log(LOGFILE_NAME);
00123 
00124   guard = new mutex();
00125 
00126   amorph<ithread> thread_list;
00127 
00128   for (int i = 0; i < DEFAULT_FISH; i++) {
00129     if (i % 2) thread_list.append(new piranha);
00130     else thread_list.append(new barracuda);
00131     // start the thread we added.
00132     thread_list[thread_list.elements() - 1]->start(NIL);
00133   }
00134 
00135   time_stamp when_to_leave(DEFAULT_RUN_TIME);
00136   while (when_to_leave > time_stamp()) { portable::sleep_ms(rando.inclusive(12, 200)); }
00137 
00138   LOG("now exiting from all threads....");
00139 
00140   // stop all the threads.  if we just reset the amorph, bad things happen,
00141   // possibly because a destructor can't manage threads in this way?  or
00142   // because the thread is using a mutex inside a destructor???
00143   for (int j = 0; j < thread_list.elements(); j++) thread_list[j]->stop();
00144   thread_list.reset();  // should stop and whack all threads.
00145 
00146   while (concurrent_biters > 0) { portable::sleep_ms(42); }
00147 
00148   LOG("done exiting from all threads....");
00149 
00150   delete guard;
00151 
00152   guards::alert_message("auto_synchronizer:: works for all functions tested.");
00153   return 0;
00154 }
00155 

Generated on Fri Nov 28 04:29:38 2008 for HOOPLE Libraries by  doxygen 1.5.1