diff options
Diffstat (limited to 'ACE/tests/Reactor_Timer_Test.cpp')
-rw-r--r-- | ACE/tests/Reactor_Timer_Test.cpp | 293 |
1 files changed, 293 insertions, 0 deletions
diff --git a/ACE/tests/Reactor_Timer_Test.cpp b/ACE/tests/Reactor_Timer_Test.cpp new file mode 100644 index 00000000000..22dfc273b7b --- /dev/null +++ b/ACE/tests/Reactor_Timer_Test.cpp @@ -0,0 +1,293 @@ + +//============================================================================= +/** + * @file Reactor_Timer_Test.cpp + * + * $Id$ + * + * This is a simple test that illustrates the timer mechanism of + * the reactor. Scheduling timers, resetting timer intervals, + * handling expired timers and cancelling scheduled timers are + * all exercised in this test. + * + * + * @author Prashant Jain <pjain@cs.wustl.edu> and Douglas C. Schmidt <schmidt@cs.wustl.edu> + */ +//============================================================================= + + +#include "test_config.h" +#include "ace/Timer_Queue.h" +#include "ace/Reactor.h" +#include "ace/High_Res_Timer.h" +#include "ace/Trace.h" +#include "ace/Recursive_Thread_Mutex.h" +#include "ace/Log_Msg.h" +#include "ace/Timer_Heap.h" +#include "ace/Auto_Ptr.h" + + + +static int done = 0; +static int the_count = 0; +static int odd = 0; + +class Time_Handler : public ACE_Event_Handler +{ +public: + /// Default constructor + Time_Handler (); + + /// Handle the timeout. + virtual int handle_timeout (const ACE_Time_Value &tv, + const void *arg); + + /// Called when <Time_Handler> is removed. + virtual int handle_close (ACE_HANDLE handle, + ACE_Reactor_Mask close_mask); + + /// Return our timer id. + long timer_id (void) const; + + /// Set our timer id; + void timer_id (long); + +private: + /// Stores the id of this timer. + long timer_id_; +}; + +Time_Handler::Time_Handler () +: timer_id_ (-1) +{ + // Nothing +} + +int +Time_Handler::handle_close (ACE_HANDLE handle, + ACE_Reactor_Mask close_mask) +{ + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("[%x] handle = %d, close_mask = %d, timer id = %d\n"), + this, + handle, + close_mask, + this->timer_id ())); + return 0; +} + +int +Time_Handler::handle_timeout (const ACE_Time_Value &tv, + const void *arg) +{ + long current_count = static_cast<long> (reinterpret_cast<size_t> (arg)); + if (current_count >= 0) + ACE_TEST_ASSERT (current_count == the_count); + + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("[%x] Timer id %d with count #%d|%d timed out at %d!\n"), + this, + this->timer_id (), + the_count, + current_count, + tv.sec ())); + + if (current_count == long (ACE_MAX_TIMERS - 1)) + done = 1; + else if (the_count == ACE_MAX_TIMERS - 1) + { + done = 1; + return -1; + } + else if (current_count == -1) + { + int result = ACE_Reactor::instance ()->reset_timer_interval (this->timer_id (), + ACE_Time_Value (the_count + 1)); + if (result == -1) + ACE_ERROR ((LM_ERROR, + ACE_TEXT ("Error resetting timer interval\n"))); + } + the_count += (1 + odd); + return 0; +} + +long +Time_Handler::timer_id (void) const +{ + return this->timer_id_; +} + +void +Time_Handler::timer_id (long t) +{ + this->timer_id_ = t; +} + +static void +test_registering_all_handlers (void) +{ + ACE_Trace t (ACE_TEXT ("test_registering_all_handler"), + __LINE__, + ACE_TEXT_CHAR_TO_TCHAR (__FILE__)); + Time_Handler rt[ACE_MAX_TIMERS]; + long t_id[ACE_MAX_TIMERS]; + + for (size_t i = 0; i < ACE_MAX_TIMERS; i++) + { + t_id[i] = + ACE_Reactor::instance ()->schedule_timer (&rt[i], + (const void *) i, + ACE_Time_Value (2 * i + 1)); + ACE_TEST_ASSERT (t_id[i] != -1); + rt[i].timer_id (t_id[i]); + } + + while (!done) + ACE_Reactor::instance ()->handle_events (); +} + +static void +test_registering_one_handler (void) +{ + ACE_Trace t (ACE_TEXT ("test_registering_one_handler"), + __LINE__, + ACE_TEXT_CHAR_TO_TCHAR (__FILE__)); + Time_Handler rt[ACE_MAX_TIMERS]; + long t_id[ACE_MAX_TIMERS]; + + done = 0; + the_count = 0; + + for (size_t i = 0; i < ACE_MAX_TIMERS; i++) + { + t_id[i] = + ACE_Reactor::instance ()->schedule_timer (&rt[0], + (const void *) i, + ACE_Time_Value (2 * i + 1)); + ACE_TEST_ASSERT (t_id[i] != -1); + } + + while (!done) + ACE_Reactor::instance ()->handle_events (); +} + +static void +test_canceling_odd_timers (void) +{ + ACE_Trace t (ACE_TEXT ("test_canceling_odd_timers"), + __LINE__, + ACE_TEXT_CHAR_TO_TCHAR (__FILE__)); + Time_Handler rt[ACE_MAX_TIMERS]; + long t_id[ACE_MAX_TIMERS]; + + done = 0; + the_count = 1; + odd = 1; + + for (size_t i = 0; i < ACE_MAX_TIMERS; i++) + { + t_id[i] = ACE_Reactor::instance ()->schedule_timer (&rt[i], + (const void *) i, + ACE_Time_Value (2 * i + 1)); + ACE_TEST_ASSERT (t_id[i] != -1); + rt[i].timer_id (t_id[i]); + } + + for (size_t j = 0; (u_long) j < ACE_MAX_TIMERS; j++) + // Cancel handlers with odd numbered timer ids. + if (ACE_ODD (rt[j].timer_id ())) + { + int result = + ACE_Reactor::instance ()->cancel_timer (rt[j].timer_id ()); + if (result == -1) + ACE_ERROR ((LM_ERROR, + ACE_TEXT ("Error cancelling timer\n"))); + } + + while (!done) + ACE_Reactor::instance ()->handle_events (); +} + +static void +test_resetting_timer_intervals (void) +{ + ACE_Trace t (ACE_TEXT ("test_resetting_timer_intervals"), + __LINE__, + ACE_TEXT_CHAR_TO_TCHAR (__FILE__)); + Time_Handler rt; + long t_id; + + done = 0; + the_count = 0; + odd = 0; + + t_id = + ACE_Reactor::instance ()->schedule_timer + (&rt, + (const void *) -1, + ACE_Time_Value (1), + // Start off by making this an interval timer. + ACE_Time_Value (1)); + + ACE_TEST_ASSERT (t_id != -1); + rt.timer_id (t_id); + + while (!done) + ACE_Reactor::instance ()->handle_events (); +} + +// If any command line arg is given, run the test with high res timer +// queue. Else run it normally. +int +run_main (int argc, ACE_TCHAR *[]) +{ + ACE_START_TEST (ACE_TEXT ("Reactor_Timer_Test")); + + if (argc > 1) + { + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("Running with high-res timer queue\n"))); + ACE_Reactor *r = ACE_Reactor::instance (); + + (void) ACE_High_Res_Timer::global_scale_factor (); + + // Change the source of time in the Reactor to the + // high-resolution timer. Why does this test require such + // precision for a 1 second timer is beyond me ... I think it + // is a cut&paste error. + // + // The use of auto_ptr<> is optional, ACE uses dangerous memory + // management idioms everywhere, I thought I could demonstrate how + // to do it right in at least one test. Notice the lack of + // ACE_NEW_RETURN, that monstrosity has no business in proper C++ + // code ... + auto_ptr<ACE_Timer_Heap_Variable_Time_Source> tq( + new ACE_Timer_Heap_Variable_Time_Source); + // ... notice how the policy is in the derived timer queue type. + // The abstract timer queue does not have a time policy ... + tq->set_time_policy(&ACE_High_Res_Timer::gettimeofday_hr); + // ... and then the timer queue is replaced. Strangely, the + // Reactor does *not* copy the timers, it just deletes the + // existing timer queue .... + r->timer_queue(tq.get()); + // ... the Reactor has assumed ownership, release the + // auto_ptr<> ... + tq.release(); + } + + // Register all different handlers, i.e., one per timer. + test_registering_all_handlers (); + + // Now try multiple timers for ONE event handler (should produce the + // same result). + test_registering_one_handler (); + + // Try canceling handlers with odd numbered timer ids. + test_canceling_odd_timers (); + + // Make sure <reset_timer_inverval> works. + test_resetting_timer_intervals (); + + ACE_END_TEST; + return 0; +} |