00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
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
00035
00036 const int DEFAULT_RUN_TIME = 142 * SECOND_ms;
00037
00038
00039 int concurrent_biters = 0;
00040
00041
00042 int grab_lock = 0;
00043
00044
00045 mutex *guard;
00046
00047
00048
00049
00050
00051 const istring LOGFILE_NAME = path_configuration::make_logfile_name
00052 ("t_auto_synch.log");
00053
00054
00055 #define LOG(to_print) log.log(timestamp(true) + istring(to_print))
00056
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
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
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
00141
00142
00143 for (int j = 0; j < thread_list.elements(); j++) thread_list[j]->stop();
00144 thread_list.reset();
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