00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include <basis/chaos.h>
00020 #include <basis/function.h>
00021 #include <basis/guards.h>
00022 #include <basis/istring.h>
00023 #include <basis/log_base.h>
00024 #include <basis/set.cpp>
00025 #include <data_struct/unique_id.h>
00026 #include <mechanisms/ithread.h>
00027 #include <mechanisms/thread_cabinet.h>
00028 #include <mechanisms/time_stamp.h>
00029 #include <opsystem/application_shell.h>
00030 #include <opsystem/event_extensions.h>
00031 #include <loggers/file_logger.h>
00032 #include <data_struct/static_memory_gremlin.h>
00033 #include <opsystem/timer_driver.h>
00034
00035 #define LOG(s) STAMPED_EMERGENCY_LOG(program_wide_logger(), s)
00036
00037 const int TEST_DURATION = 3 * MINUTE_ms;
00038
00039 const int MAX_THREADS = 120;
00040
00042
00043 class timer_driver_tester : public application_shell
00044 {
00045 public:
00046 timer_driver_tester()
00047 : application_shell(static_class_name()), _in_progress(false) {}
00048 IMPLEMENT_CLASS_NAME("timer_driver_tester");
00049 virtual ~timer_driver_tester() {}
00050
00051 int execute();
00052
00053 thread_cabinet &threads() { return _threads; }
00054
00055 bool in_progress() const { return _in_progress; }
00056
00057
00058
00059 private:
00060 bool _in_progress;
00061
00062
00063
00064 thread_cabinet _threads;
00065 };
00066
00068
00069 class timer_test_thread : public ithread
00070 {
00071 public:
00072 timer_test_thread(application_shell &parent)
00073 : ithread(parent.randomizer().inclusive(20, 480)), _parent(parent)
00074 { start(NIL); }
00075
00076 IMPLEMENT_CLASS_NAME("timer_test_thread");
00077 void perform_activity(void *) {
00078 FUNCDEF("perform_activity");
00079 if (time_stamp() < _started)
00080 deadly_error(class_name(), func, "start time is before current time.");
00081 if (time_stamp() < _last)
00082 deadly_error(class_name(), func, "last check is before current time.");
00083 _last.reset();
00084 time_stamp ted;
00085 time_stamp jed;
00086 if (ted > jed)
00087 deadly_error(class_name(), func, "jed is less than test.");
00088 }
00089
00090 private:
00091 application_shell &_parent;
00092 time_stamp _started;
00093 time_stamp _last;
00094 };
00095
00097
00098 class my_timer_handler : public timed_object
00099 {
00100 public:
00101 my_timer_handler(timer_driver_tester &parent, int id) : _id(id), _parent(parent) {}
00102 virtual ~my_timer_handler() {}
00103 IMPLEMENT_CLASS_NAME("my_timer_handler");
00104
00105 virtual void handle_timer_callback() {
00106 FUNCDEF("handle_timer_callback");
00107 if (_parent.in_progress())
00108 LOG("saw in progress flag set to true! we interrupted real "
00109 "ops, not just sleep!");
00110 LOG(isprintf("timer%d hit.", _id));
00111 timer_test_thread *new_thread = new timer_test_thread(_parent);
00112 unique_int id = _parent.threads().add_thread(new_thread, false, NIL);
00113
00114 if (!id)
00115 deadly_error(class_name(), func, "failed to start a new thread.");
00116
00117 if (_parent.threads().threads() > MAX_THREADS) {
00118 int gone_index = _parent.randomizer().inclusive(0, _parent.threads().threads() - 1);
00119 unique_int gone_thread = _parent.threads().thread_ids()[gone_index];
00120 _parent.threads().cancel_thread(gone_thread);
00121 portable::sleep_ms(100);
00122 }
00123 _parent.threads().clean_debris();
00124
00125 LOG(isprintf("%d threads checking time_stamp.", _parent.threads().threads()));
00126 }
00127
00128 private:
00129 int _id;
00130 timer_driver_tester &_parent;
00131 };
00132
00134
00135 #define CREATE_TIMER(name, id, dur) \
00136 my_timer_handler name(*this, id); \
00137 program_wide_timer().set_timer(dur, &name); \
00138 LOG(istring("timer ") + #name + " hitting every " \
00139 + #dur + " ms")
00140
00141 #define ZAP_TIMER(name) \
00142 program_wide_timer().zap_timer(&name)
00143
00144 int timer_driver_tester::execute()
00145 {
00146 SET_DEFAULT_COMBO_LOGGER;
00147
00148 CREATE_TIMER(timer1, 1, 500);
00149
00150 CREATE_TIMER(timer2, 2, SECOND_ms);
00151 CREATE_TIMER(timer3, 3, 3 * SECOND_ms);
00152 CREATE_TIMER(timer4, 4, 8 * SECOND_ms);
00153 CREATE_TIMER(timer5, 5, 12 * SECOND_ms);
00154
00155 LOG("pausing for a while...");
00156 time_stamp when_done(TEST_DURATION);
00157 while (time_stamp() < when_done) {
00158 _in_progress = true;
00159
00160
00161
00162 int scrob = 1;
00163 for (int i = 1; i < 50; i++) {
00164 scrob *= i;
00165 }
00166 _in_progress = false;
00167 #ifdef __UNIX__
00168 portable::sleep_ms(100);
00169 #else
00170 bool okay = event_extensions::poll();
00171 if (!okay) break;
00172 #endif
00173 }
00174
00175 guards::alert_message("timer_driver:: works for all functions tested (if messages seem appropriate).");
00176
00177 ZAP_TIMER(timer1);
00178 ZAP_TIMER(timer2);
00179 ZAP_TIMER(timer3);
00180 ZAP_TIMER(timer4);
00181 ZAP_TIMER(timer5);
00182
00183 return 0;
00184 }
00185
00187
00188 HOOPLE_MAIN(timer_driver_tester, )
00189