test timer driver is working again
authorFred T. Hamster <fred@feistymeow.org>
Sun, 8 Feb 2026 20:43:44 +0000 (15:43 -0500)
committerFred T. Hamster <fred@feistymeow.org>
Sun, 8 Feb 2026 20:43:44 +0000 (15:43 -0500)
had to bring back some old windoze code for it, in event_extensions.  this will not build for real yet on windows, but that's a task for another day.
the tester is working great on linux!

15 files changed:
nucleus/library/application/event_extensions.cpp [new file with mode: 0644]
nucleus/library/application/event_extensions.h [new file with mode: 0644]
nucleus/library/application/makefile
nucleus/library/application/windoze_helper.cpp
nucleus/library/application/windoze_helper.h
nucleus/library/tests_application/aa-readme.txt [deleted file]
nucleus/library/tests_application/aa_readme.txt [new file with mode: 0644]
nucleus/library/tests_application/makefile
nucleus/library/tests_application/test_timer_driver.cpp [deleted file]
nucleus/library/tests_timely/makefile
nucleus/library/tests_timely/test_earth_time.cpp
nucleus/library/tests_timely/test_stopwatch.cpp
nucleus/library/tests_timely/test_timer_driver.cpp [new file with mode: 0644]
nucleus/library/timely/timer_driver.cpp
scripts/buildor/upgrade_hoople_to_feistymeow.sh

diff --git a/nucleus/library/application/event_extensions.cpp b/nucleus/library/application/event_extensions.cpp
new file mode 100644 (file)
index 0000000..92de807
--- /dev/null
@@ -0,0 +1,93 @@
+#ifndef EVENT_EXTENSIONS_IMPLEMENTATION_FILE
+#define EVENT_EXTENSIONS_IMPLEMENTATION_FILE
+
+/*****************************************************************************\
+*                                                                             *
+*  Name   : event_extensions                                                  *
+*  Author : Chris Koeritz                                                     *
+*                                                                             *
+*******************************************************************************
+* Copyright (c) 1995-$now By Author.  This program is free software; you can  *
+* redistribute it and/or modify it under the terms of the GNU General Public  *
+* License as published by the Free Software Foundation; either version 2 of   *
+* the License or (at your option) any later version.  This is online at:      *
+*     http://www.fsf.org/copyleft/gpl.html                                    *
+* Please send any updates to: fred@gruntose.com                               *
+\*****************************************************************************/
+
+#ifdef __WIN32__
+
+#include "event_extensions.h"
+
+#include <basis/guards.h>
+#include <basis/portable.h>
+#include <mechanisms/time_stamp.h>
+
+#include <mmsystem.h>
+
+bool event_extensions::poll()
+{
+  MSG message;
+  return poll(message);
+}
+
+bool event_extensions::poll(MSG &message)
+{
+  return windoze_helper::event_poll(message);
+/*
+  message.hwnd = 0;
+  message.message = 0;
+  message.wParam = 0;
+  message.lParam = 0;
+  if (PeekMessage(&message, NIL, 0, 0, PM_REMOVE)) {
+    TranslateMessage(&message);
+    DispatchMessage(&message);
+  }
+  return true;
+*/
+}
+
+bool event_extensions::poll(int wait)
+{
+  time_stamp start_time;
+  do {
+    MSG message;
+    if (!poll(message)) return false;
+  } while (wait && (time_stamp().value() - start_time.value() <= wait));
+  return true;
+}
+
+bool event_extensions::poll_on_message(window_handle handle, UINT look_for,
+    int wait, MSG &message)
+{
+  time_stamp start_time;
+  do {
+    bool okay = poll(message);
+    if (!okay) return false;
+    if ( (message.hwnd == handle) && (message.message == look_for) )
+      return true;
+  } while (time_stamp().value() - start_time.value() <= wait);
+    // keep going while time is left.
+  return false;
+}
+
+bool event_extensions::poll_on_message_and_wparam(window_handle handle,
+    UINT look_for, WPARAM look_also, int wait, MSG &message)
+{
+  time_stamp start_time;
+  do {
+    bool okay = poll(message);
+    if (!okay) return false;
+    if ( (message.hwnd == handle) && (message.wParam == look_also)
+          && (message.message == look_for) )
+      return true;
+  } while (time_stamp().value() - start_time.value() <= wait);
+    // keep going while time is left.
+  return false;
+}
+
+#endif
+
+
+#endif //EVENT_EXTENSIONS_IMPLEMENTATION_FILE
+
diff --git a/nucleus/library/application/event_extensions.h b/nucleus/library/application/event_extensions.h
new file mode 100644 (file)
index 0000000..9b671db
--- /dev/null
@@ -0,0 +1,60 @@
+#ifndef EVENT_EXTENSIONS_CLASS
+#define EVENT_EXTENSIONS_CLASS
+
+/*****************************************************************************\
+*                                                                             *
+*  Name   : event_extensions                                                  *
+*  Author : Chris Koeritz                                                     *
+*                                                                             *
+*******************************************************************************
+* Copyright (c) 1995-$now By Author.  This program is free software; you can  *
+* redistribute it and/or modify it under the terms of the GNU General Public  *
+* License as published by the Free Software Foundation; either version 2 of   *
+* the License or (at your option) any later version.  This is online at:      *
+*     http://www.fsf.org/copyleft/gpl.html                                    *
+* Please send any updates to: fred@gruntose.com                               *
+\*****************************************************************************/
+
+//! Provides some useful extensions to event handling in windows.
+
+#ifdef __WIN32__
+
+#include "opsysdll.h"
+
+#include <basis/istring.h>
+#include <basis/portable.h>
+
+class OPSYSTEM_CLASS_STYLE event_extensions
+{
+public:
+  static bool poll();
+    //!< allows one event to be processed.
+    /*!< this will possibly yield control to other programs also.  if an event
+    is processed, then true is returned.  if no event was found, then false
+    is returned. */
+
+  static bool poll(MSG &message);
+    //!< processes one event like poll, but returns what the event was.
+    /*!< if no message was processed, then "message" is reset to zeros. */
+
+  static bool poll(int wait);
+    //!< polls for events until the "wait" time (in milliseconds) has elapsed.
+    /*!< this does not block other windows in the program because events are
+    still being handled.  the return value is true if the poll completed
+    successfully and false if it had to abort for some reason. */
+
+  static bool poll_on_message(window_handle handle, UINT msg, int wait,
+        MSG &found);
+    //!< polls awaiting the message "msg" for the window "win".
+    /*!< if the message is found within "wait" milliseconds, then it is
+    stored in "found" and true is returned.  otherwise, false is returned. */
+
+  static bool poll_on_message_and_wparam(window_handle handle, UINT msg,
+        WPARAM wparam, int wait, MSG &found);
+    //!< like poll_on_message, but also requires the wParam to equal "wparam".
+};
+
+#endif  // win32.
+
+#endif  // outer guard.
+
index c2548b55e2280c7f0fc4dad7272b1c598857f13b..c564ff4c3ce90889b23a8384b444a197ec84efbb 100644 (file)
@@ -2,9 +2,10 @@ include cpp/variables.def
 
 PROJECT = application
 TYPE = library
-SOURCE = application_shell.cpp callstack_tracker.cpp command_line.cpp dll_root.cpp \
-  hoople_service.cpp launch_manager.cpp memory_checker.cpp redirecter.cpp \
-  registry_config.cpp shared_memory.cpp singleton_application.cpp windoze_helper.cpp
+SOURCE = application_shell.cpp callstack_tracker.cpp command_line.cpp \
+  dll_root.cpp event_extensions.cpp hoople_service.cpp launch_manager.cpp \
+  memory_checker.cpp redirecter.cpp registry_config.cpp shared_memory.cpp \
+  singleton_application.cpp windoze_helper.cpp
 TARGETS = application.lib
 LOCAL_LIBS_USED = basis
 
index 1dfbefad9c3715ede6f84ae3f96757b3d1bfb3f2..7e643faa98bf31d4e86d38c195ef8766b59ec91d 100644 (file)
@@ -300,6 +300,7 @@ istring null_device()
   return "/dev/null";
 #endif
 }
+*/
 
 #ifdef __WIN32__
 bool event_poll(MSG &message)
@@ -316,6 +317,8 @@ bool event_poll(MSG &message)
 }
 #endif
 
+/*
+
 // makes a complaint about a failure.
 #ifndef EMBEDDED_BUILD
   #define COMPLAIN_QUERY(to_print) { \
index 9a149a4193229836928d8a993bf1200515123d90..1c0bab935441364bac8ad909de204fcf1c962c3f 100644 (file)
@@ -199,7 +199,7 @@ namespace application {
   // ms-windows of more modern types, i.e. win32.
   #ifdef __WIN32__
 
-//    bool event_poll(MSG &message);
+    bool event_poll(MSG &message);
       //!< tries to process one win32 event and retrieve the "message" from it.
       /*!< this is a very general poll and will retrieve any message that's
       available for the current thread.  the message is actually processed
diff --git a/nucleus/library/tests_application/aa-readme.txt b/nucleus/library/tests_application/aa-readme.txt
deleted file mode 100644 (file)
index 51fa928..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-
-this is in transit, being brought back from cold storage.
-
-also, this is called tests_application currently, but the actual code seems to come from all over
-the newer feisty library configuration.
-eventually we may want to move the tests into specifically named folders for what they're testing.
-
-
-
-
-========================================
-= potential testings for application lib
-========================================
-
-DONE: application_shell.h
-DONE: base_application.h
-DONE: build_configuration.h
-callstack_tracker.h
-DONE: command_line.h
-DONE: hoople_main.h
-hoople_service.h
-launch_manager.h
-memory_checker.h
-redirecter.h
-registry_config.h
-shared_memory.h
-singleton_application.h
-window_classist.h
-windoze_helper.h
diff --git a/nucleus/library/tests_application/aa_readme.txt b/nucleus/library/tests_application/aa_readme.txt
new file mode 100644 (file)
index 0000000..aa4670e
--- /dev/null
@@ -0,0 +1,32 @@
+
+this is in transit, being brought back from cold storage.
+
+also, this is called tests_application currently, but the actual code seems to come from all over
+the newer feisty library configuration.
+eventually we may want to move the tests into specifically named folders for what they're testing.
+
+
+
+
+========================================
+= potential testings for application lib
+========================================
+
+DONE: application_shell.h
+DONE: base_application.h
+DONE: build_configuration.h
+callstack_tracker.h
+DONE: command_line.h
+DONE: hoople_main.h
+hoople_service.h
+launch_manager.h
+memory_checker.h
+redirecter.h
+DONE: registry_config.h
+shared_memory.h
+singleton_application.h
+window_classist.h
+windoze_helper.h
+
+
+
index 99d375365937a4276ccef39dd3b3bdd5a3a031dc..ab587320a9cdb69617ea2bfdc4a3fd2a9eab4f1a 100644 (file)
@@ -6,21 +6,10 @@ PROJECT = tests_application
 TYPE = test
 TARGETS = test_break_signal.exe test_command_line.exe test_path_configuration.exe \
   test_registry_configurator.exe 
-#  test_logger.exe \
-#  test_redirection.exe \
-#  test_rendezvous.exe test_system_values.exe test_timer_driver.exe
-#ifeq "$(findstring EMBEDDED_BUILD, $(DEFINITIONS))" ""
-#  TARGETS += test_shared_memory.exe 
-#endif
-##LOCAL_LIBS_USED = basis i_library 
 DEFINITIONS += USE_FEISTY_MEOW_DLLS
 LOCAL_LIBS_USED = unit_test application configuration filesystem loggers \
   mathematics nodes processes structures textual timely structures basis
 RUN_TARGETS = $(ACTUAL_TARGETS)
 
-#  test_logger.exe \
-#  test_path_configuration.exe test_registry_configurator.exe \
-#  test_system_values.exe test_timer_driver.exe
-
 include cpp/rules.def
 
diff --git a/nucleus/library/tests_application/test_timer_driver.cpp b/nucleus/library/tests_application/test_timer_driver.cpp
deleted file mode 100644 (file)
index ba7fff1..0000000
+++ /dev/null
@@ -1,189 +0,0 @@
-/*****************************************************************************\
-*                                                                             *
-*  Name   : t_timer_driver                                                    *
-*  Author : Chris Koeritz                                                     *
-*                                                                             *
-*  Purpose:                                                                   *
-*                                                                             *
-*    Tests the timer driver class from the operating system library.          *
-*                                                                             *
-*******************************************************************************
-* Copyright (c) 2005-$now By Author.  This program is free software; you can  *
-* redistribute it and/or modify it under the terms of the GNU General Public  *
-* License as published by the Free Software Foundation; either version 2 of   *
-* the License or (at your option) any later version.  This is online at:      *
-*     http://www.fsf.org/copyleft/gpl.html                                    *
-* Please send any updates to: fred@gruntose.com                               *
-\*****************************************************************************/
-
-#include <basis/chaos.h>
-#include <basis/function.h>
-#include <basis/guards.h>
-#include <basis/istring.h>
-#include <basis/log_base.h>
-#include <basis/set.h>
-#include <data_struct/unique_id.h>
-#include <mechanisms/ithread.h>
-#include <mechanisms/thread_cabinet.h>
-#include <mechanisms/time_stamp.h>
-#include <opsystem/application_shell.h>
-#include <opsystem/event_extensions.h>
-#include <loggers/file_logger.h>
-#include <data_struct/static_memory_gremlin.h>
-#include <opsystem/timer_driver.h>
-
-#define LOG(s) STAMPED_EMERGENCY_LOG(program_wide_logger(), s)
-
-const int TEST_DURATION = 3 * MINUTE_ms;
-
-const int MAX_THREADS = 120;
-
-////////////////////////////////////////////////////////////////////////////
-
-class timer_driver_tester : public application_shell
-{
-public:
-  timer_driver_tester()
-      : application_shell(static_class_name()), _in_progress(false) {}
-  IMPLEMENT_CLASS_NAME("timer_driver_tester");
-  virtual ~timer_driver_tester() {}
-
-  int execute();
-
-  thread_cabinet &threads() { return _threads; }
-
-  bool in_progress() const { return _in_progress; }
-    // returns true if activity is currently occurring on the main thread.
-    // we don't expect this activity to be interrupted by timer events.
-
-private:
-  bool _in_progress;
-    // simple flag to check when a timer hits.  if this is true, then a timer
-    // hit while we were doing actual functional operations, rather than
-    // just waiting in a sleep.
-  thread_cabinet _threads;  // storage for our time_stamp testing threads.
-};
-
-////////////////////////////////////////////////////////////////////////////
-
-class timer_test_thread : public ithread
-{
-public:
-  timer_test_thread(application_shell &parent)
-      : ithread(parent.randomizer().inclusive(20, 480)), _parent(parent)
-  { start(NIL); }
-
-  IMPLEMENT_CLASS_NAME("timer_test_thread");
-  void perform_activity(void *) {
-    FUNCDEF("perform_activity");
-    if (time_stamp() < _started)
-      deadly_error(class_name(), func, "start time is before current time.");
-    if (time_stamp() < _last) 
-      deadly_error(class_name(), func, "last check is before current time.");
-    _last.reset();  // set the last time to right now.
-    time_stamp ted;
-    time_stamp jed;
-    if (ted > jed)
-      deadly_error(class_name(), func, "jed is less than test.");
-  }
-
-private:
-  application_shell &_parent;
-  time_stamp _started;
-  time_stamp _last;
-};
-
-////////////////////////////////////////////////////////////////////////////
-
-class my_timer_handler : public timed_object
-{
-public:
-  my_timer_handler(timer_driver_tester &parent, int id) : _id(id), _parent(parent) {}
-  virtual ~my_timer_handler() {}
-  IMPLEMENT_CLASS_NAME("my_timer_handler");
-
-  virtual void handle_timer_callback() {
-    FUNCDEF("handle_timer_callback");
-    if (_parent.in_progress())
-      LOG("saw in progress flag set to true!  we interrupted real "
-          "ops, not just sleep!");
-    LOG(isprintf("timer%d hit.", _id));
-    timer_test_thread *new_thread = new timer_test_thread(_parent);
-    unique_int id = _parent.threads().add_thread(new_thread, false, NIL);
-      // the test thread auto-starts, so we don't let the cabinet start it.
-    if (!id)
-      deadly_error(class_name(), func, "failed to start a new thread.");
-
-    if (_parent.threads().threads() > MAX_THREADS) {
-      int gone_index = _parent.randomizer().inclusive(0, _parent.threads().threads() - 1);
-      unique_int gone_thread = _parent.threads().thread_ids()[gone_index];
-      _parent.threads().cancel_thread(gone_thread);
-      portable::sleep_ms(100);  // allow thread to start up.
-    }
-    _parent.threads().clean_debris();  // toss any dead threads.
-
-    LOG(isprintf("%d threads checking time_stamp.", _parent.threads().threads()));
-  }
-
-private:
-  int _id;
-  timer_driver_tester &_parent;
-};
-
-////////////////////////////////////////////////////////////////////////////
-
-#define CREATE_TIMER(name, id, dur) \
-  my_timer_handler name(*this, id); \
-  program_wide_timer().set_timer(dur, &name); \
-  LOG(istring("timer ") + #name + " hitting every " \
-      + #dur + " ms")
-
-#define ZAP_TIMER(name) \
-  program_wide_timer().zap_timer(&name)
-
-int timer_driver_tester::execute()
-{
-  SET_DEFAULT_COMBO_LOGGER;
-
-  CREATE_TIMER(timer1, 1, 500);
-//  CREATE_TIMER(timer1, 1, 10);
-  CREATE_TIMER(timer2, 2, SECOND_ms);
-  CREATE_TIMER(timer3, 3, 3 * SECOND_ms);
-  CREATE_TIMER(timer4, 4, 8 * SECOND_ms);
-  CREATE_TIMER(timer5, 5, 12 * SECOND_ms);
-
-  LOG("pausing for a while...");
-  time_stamp when_done(TEST_DURATION);
-  while (time_stamp() < when_done) {
-    _in_progress = true;
-    // do some various calculations in here and see if we're interrupted
-    // during them.  it's one thing to be interrupted in the middle of a
-    // sleep, but it's much different to be interrupted in mid operation.
-    int scrob = 1;
-    for (int i = 1; i < 50; i++) {
-      scrob *= i;
-    }
-    _in_progress = false;    
-#ifdef __UNIX__
-    portable::sleep_ms(100);
-#else
-    bool okay = event_extensions::poll();
-    if (!okay) break;
-#endif
-  }
-
-  guards::alert_message("timer_driver:: works for all functions tested (if messages seem appropriate).");
-
-  ZAP_TIMER(timer1);
-  ZAP_TIMER(timer2);
-  ZAP_TIMER(timer3);
-  ZAP_TIMER(timer4);
-  ZAP_TIMER(timer5);
-
-  return 0;
-}
-
-////////////////////////////////////////////////////////////////////////////
-
-HOOPLE_MAIN(timer_driver_tester, )
-
index f3690f45ff3c9587c290ce832413287a280dd40d..db6d5f65ded5f1a0e0fcf29d2998561a95928861 100644 (file)
@@ -2,7 +2,7 @@ include cpp/variables.def
 
 PROJECT = tests_timely
 TYPE = test
-TARGETS = test_earth_time.exe test_stopwatch.exe
+TARGETS = test_earth_time.exe test_stopwatch.exe test_timer_driver.exe
 DEFINITIONS += USE_FEISTY_MEOW_DLLS
 LOCAL_LIBS_USED = unit_test application processes loggers configuration mathematics nodes \
   structures textual timely filesystem structures basis 
index 75b7770f0d50f11d1c1b0df83e2d5fbbf9fba79d..373a19d73d80e3f58add00e38bdf83fb22cbb9b6 100644 (file)
@@ -145,6 +145,8 @@ int test_earth_time::execute()
   run_test_02(); 
   run_test_03(); 
 
+  critical_events::alert_message(astring(class_name()) + ": works for those functions tested.");
+
   return final_report();
 }
 
index 6352cba9cccb5079391c8fb35b0d23180dcba64f..fd20ca020fcc9a2df3b7b4c858bfef4a70cdf0f7 100644 (file)
@@ -81,7 +81,8 @@ int test_stopwatch::execute()
     deadly_error(class_name(), "second", "unacceptable timer deviation");
   fred_time.reset();
 
-  critical_events::alert_message("stopwatch:: works for those functions tested.");
+  critical_events::alert_message(astring(class_name()) + ": works for those functions tested.");
+
   return 0;
 }
 
diff --git a/nucleus/library/tests_timely/test_timer_driver.cpp b/nucleus/library/tests_timely/test_timer_driver.cpp
new file mode 100644 (file)
index 0000000..4eb3a1c
--- /dev/null
@@ -0,0 +1,208 @@
+/*****************************************************************************\
+*                                                                             *
+*  Name   : t_timer_driver                                                    *
+*  Author : Chris Koeritz                                                     *
+*                                                                             *
+*  Purpose:                                                                   *
+*                                                                             *
+*    Tests the timer driver class from the operating system library.          *
+*                                                                             *
+*******************************************************************************
+* Copyright (c) 2005-$now By Author.  This program is free software; you can  *
+* redistribute it and/or modify it under the terms of the GNU General Public  *
+* License as published by the Free Software Foundation; either version 2 of   *
+* the License or (at your option) any later version.  This is online at:      *
+*     http://www.fsf.org/copyleft/gpl.html                                    *
+* Please send any updates to: fred@gruntose.com                               *
+\*****************************************************************************/
+
+#include <application/application_shell.h>
+#include <application/event_extensions.h>
+#include <application/hoople_main.h>
+#include <basis/functions.h>
+#include <basis/guards.h>
+#include <basis/astring.h>
+#include <loggers/critical_events.h>
+#include <loggers/program_wide_logger.h>
+#include <loggers/file_logger.h>
+#include <mathematics/chaos.h>
+#include <processes/ethread.h>
+#include <processes/thread_cabinet.h>
+#include <structures/set.h>
+#include <structures/unique_id.h>
+#include <structures/static_memory_gremlin.h>
+#include <timely/time_control.h>
+#include <timely/time_stamp.h>
+#include <timely/timer_driver.h>
+#include <unit_test/unit_base.h>
+
+using namespace application;
+using namespace basis;
+using namespace filesystem;
+using namespace loggers;
+using namespace processes;
+using namespace structures;
+using namespace timely;
+using namespace unit_test;
+
+#define LOG(s) STAMPED_EMERGENCY_LOG(program_wide_logger::get(), s)
+
+const int DEFAULT_TEST_DURATION = 3 * SECOND_ms;
+  // with no arguments to the test, we'll run timers for this very short duration.
+
+const int MAX_THREADS = 120;
+
+//////////////
+
+class timer_driver_tester : virtual public unit_base, virtual public application_shell
+{
+public:
+  timer_driver_tester()
+      : application_shell(), _in_progress(false) {}
+  DEFINE_CLASS_NAME("timer_driver_tester");
+  virtual ~timer_driver_tester() {}
+
+  int execute();
+
+  thread_cabinet &threads() { return _threads; }
+
+  bool in_progress() const { return _in_progress; }
+    // returns true if activity is currently occurring on the main thread.
+    // we don't expect this activity to be interrupted by timer events.
+
+private:
+  bool _in_progress;
+    // simple flag to check when a timer hits.  if this is true, then a timer
+    // hit while we were doing actual functional operations, rather than
+    // just waiting in a sleep.
+  thread_cabinet _threads;  // storage for our time_stamp testing threads.
+};
+
+//////////////
+
+class timer_test_thread : public ethread
+{
+public:
+  timer_test_thread(application_shell &parent)
+      : ethread(parent.randomizer().inclusive(8, 25)), _parent(parent)
+  { start(NULL_POINTER); }
+
+  DEFINE_CLASS_NAME("timer_test_thread");
+  void perform_activity(void *) {
+    FUNCDEF("perform_activity");
+    if (time_stamp() < _started)
+      deadly_error(class_name(), func, "start time is before current time.");
+    if (time_stamp() < _last) 
+      deadly_error(class_name(), func, "last check is before current time.");
+    _last.reset();  // set the last time to right now.
+    time_stamp ted;
+    time_stamp jed;
+    if (ted > jed)
+      deadly_error(class_name(), func, "jed is less than test.");
+  }
+
+private:
+  application_shell &_parent;
+  time_stamp _started;
+  time_stamp _last;
+};
+
+//////////////
+
+class my_timer_handler : public timeable
+{
+public:
+  my_timer_handler(timer_driver_tester &parent, int id) : _id(id), _parent(parent) {}
+  virtual ~my_timer_handler() {}
+  DEFINE_CLASS_NAME("my_timer_handler");
+
+  virtual void handle_timer_callback() {
+    FUNCDEF("handle_timer_callback");
+    if (_parent.in_progress())
+      LOG("saw in progress flag set to true!  we interrupted real "
+          "ops, not just sleep!");
+    LOG(a_sprintf("timer%d hit.", _id));
+    timer_test_thread *new_thread = new timer_test_thread(_parent);
+    unique_int id = _parent.threads().add_thread(new_thread, false, NULL_POINTER);
+      // the test thread auto-starts, so we don't let the cabinet start it.
+    if (!id)
+      deadly_error(class_name(), func, "failed to start a new thread.");
+
+    if (_parent.threads().threads() > MAX_THREADS) {
+      int gone_index = _parent.randomizer().inclusive(0, _parent.threads().threads() - 1);
+      unique_int gone_thread = _parent.threads().thread_ids()[gone_index];
+      _parent.threads().cancel_thread(gone_thread);
+      time_control::sleep_ms(100);  // allow thread to start up.
+    }
+    _parent.threads().clean_debris();  // toss any dead threads.
+
+    LOG(a_sprintf("%d threads checking time_stamp.", _parent.threads().threads()));
+  }
+
+private:
+  int _id;
+  timer_driver_tester &_parent;
+};
+
+//////////////
+
+#define CREATE_TIMER(name, id, dur) \
+  my_timer_handler name(*this, id); \
+  program_wide_timer().set_timer(dur, &name); \
+  LOG(astring("created timer ") + #name + " which hits every " + #dur + " ms")
+
+#define ZAP_TIMER(name) \
+  program_wide_timer().zap_timer(&name)
+
+int timer_driver_tester::execute()
+{
+  int next_id = 1001;  // we start issuing timer IDs at 1001 for this test.
+
+  int runtime_ms = DEFAULT_TEST_DURATION;
+  if (application::_global_argc >= 2) {
+    astring passed_runtime = application::_global_argv[1];
+    runtime_ms = passed_runtime.convert(DEFAULT_TEST_DURATION);
+  }
+
+  // some odd timer cycles below to avoid waiting longer than our short default.
+  CREATE_TIMER(timer1, unique_int(next_id++).raw_id(), 1 * SECOND_ms);
+  CREATE_TIMER(timer2, unique_int(next_id++).raw_id(), 250);
+  CREATE_TIMER(timer3, unique_int(next_id++).raw_id(), 3 * SECOND_ms);
+  CREATE_TIMER(timer4, unique_int(next_id++).raw_id(), 140);
+  CREATE_TIMER(timer5, unique_int(next_id++).raw_id(), 500);
+
+  LOG("pausing for a while...");
+  time_stamp when_done(runtime_ms);
+  while (time_stamp() < when_done) {
+    _in_progress = true;
+    // do some various calculations in here and see if we're interrupted
+    // during them.  it's one thing to be interrupted in the middle of a
+    // sleep, but it's much different to be interrupted in mid operation.
+    int scrob = 1;
+    for (int i = 1; i < 50; i++) {
+      scrob *= i;
+    }
+    _in_progress = false;    
+#ifdef __UNIX__
+    time_control::sleep_ms(100);
+#else
+    bool okay = event_extensions::poll();
+    if (!okay) break;
+#endif
+  }
+
+  ZAP_TIMER(timer1);
+  ZAP_TIMER(timer2);
+  ZAP_TIMER(timer3);
+  ZAP_TIMER(timer4);
+  ZAP_TIMER(timer5);
+
+  critical_events::alert_message(astring(class_name()) + ": works for those functions tested.");
+
+  return 0;
+}
+
+//////////////
+
+HOOPLE_MAIN(timer_driver_tester, )
+
index 8b6a5fbd6589d6aca233306fe316e62d220983d3..1f5421c97e59bf87936301f71fe1fe434db0dac2 100644 (file)
@@ -36,7 +36,7 @@ using namespace timely;
   // uncomment for noisy code.
 
 #undef LOG
-#define LOG(tpr) printf("%s", (time_stamp::notarize() + "timer_driver::" + func + tpr).s() )
+#define LOG(tpr) printf("%s\n", (time_stamp::notarize() + "timer_driver::" + func + ": " + tpr).s() )
 
 namespace timely {
 
@@ -285,9 +285,9 @@ void timer_driver::handle_system_timer()
   }
   unhook_OS_timer();
 
-#ifdef DEBUG_TIMER_DRIVER
-  LOG("into handling OS timer...");
-#endif
+//#ifdef DEBUG_TIMER_DRIVER
+//  LOG("into handling OS timer...");
+//#endif
 
   array<driven_object_record *> to_invoke_now;
 
@@ -376,9 +376,9 @@ void timer_driver::handle_system_timer()
     }
   }
 
-#ifdef DEBUG_TIMER_DRIVER
-  LOG("done handling OS timer.");
-#endif
+//#ifdef DEBUG_TIMER_DRIVER
+//  LOG("done handling OS timer.");
+//#endif
 
   // set the next expiration time to the smallest next guy.
   reset_OS_timer(next_timer_duration);
@@ -426,18 +426,20 @@ void timer_driver::hookup_OS_timer(int duration)
 
 void timer_driver::unhook_OS_timer()
 {
-#ifdef DEBUG_TIMER_DRIVER
-  FUNCDEF("unhook_OS_timer");
-#endif
+//#ifdef DEBUG_TIMER_DRIVER
+//  FUNCDEF("unhook_OS_timer");
+//#endif
+
 //#if defined(__UNIX__) || defined(__GNU_WINDOWS__)
   // postpone the thread for quite a while so we can take care of business.
   _prompter->reschedule(LONG_TIME);
 //#elif defined(_MSC_VER)
 //  if (_real_timer_id) KillTimer(NULL_POINTER, (UINT_PTR)_real_timer_id);
 //#endif
-#ifdef DEBUG_TIMER_DRIVER
-  LOG("unhooked OS timer.");
-#endif
+
+//#ifdef DEBUG_TIMER_DRIVER
+//  LOG("unhooked OS timer.");
+//#endif
 }
 
 void timer_driver::reset_OS_timer(int next_hit)
index 61802fe402dc5fec9843346f0bf3c61586f9f5e0..79b16e4967b6748a57f204fcba2fbbfab7241086 100644 (file)
@@ -157,6 +157,7 @@ standards and usages."
     | sed -e 's/^#include <opsystem\/ini_parser.h> *$/#include <configuration\/ini_parser.h>/g' \
     | sed -e 's/^#include <opsystem\/system_values.h> *$/#include <configuration\/system_values.h>/g' \
     | sed -e 's/^#include <opsystem\/registry_config.h> *$/#include <application\/registry_config.h>/g' \
+    | sed -e 's/^#include <opsystem\/event_extensions.h> *$/#include <application\/event_extensions.h>/g' \
     | sed -e 's/log_base::NO_ENDING/parser_bits::NO_ENDING/g' \
     | sed -e 's/log_base::CRLF_AT_END/parser_bits::CRLF_AT_END/g' \
     | sed -e 's/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/[\/]*/\/\/\/\/\/\/\/\/\/\/\/\/\/\//g' \