t_semaphore.cpp

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

Generated on Fri Nov 21 04:30:09 2008 for HOOPLE Libraries by  doxygen 1.5.1