//============================================================================= /** * @file Reactor_Timer_Queue_Test.cpp * * This example tests the timer queue mechanism of ACE_Reactor. * * @author Nanbor Wang and Sergio Flores-Gaitan */ //============================================================================= #include "ace/OS_NS_sys_time.h" #include "ace/Thread_Manager.h" #include "ace/Select_Reactor.h" #include "ace/Reactor.h" #include "ace/Timer_Heap.h" #include "Driver.h" #include "Reactor_Timer_Queue_Test.h" void Reactor_Timer_Handler::set_timer_id (long tid) { this->tid_ = tid; } int Reactor_Timer_Handler::handle_timeout (const ACE_Time_Value &, const void *) { ACE_Time_Value txv = ACE_OS::gettimeofday (); ACE_DEBUG ((LM_DEBUG, "\nTimer #%d fired at %d.%06d (%T)!\n", this->tid_, txv.sec (), txv.usec ())); delete this; return 0; } Input_Handler::Input_Handler (ACE_Timer_Queue *tq, Reactor_Timer_Queue_Test_Driver &timer_queue_driver) : done_ (0), driver_ (timer_queue_driver) { this->tq_ = tq; } int Input_Handler::done (void) { return this->done_; } int Input_Handler::schedule_timer (void *argument) { int delay = *(int *) argument; Reactor_Timer_Handler *th; long tid; th = new Reactor_Timer_Handler; if (th != 0) { tid = this->reactor ()->schedule_timer (th, 0, ACE_Time_Value (0, delay)); if (tid == -1) ACE_DEBUG ((LM_DEBUG, "Unable to schedule timer\n")); else { ACE_DEBUG ((LM_DEBUG, "Timer #%d schedule to fire after %d usec from now.\n", tid, delay)); th->set_timer_id (tid); } } else ACE_ERROR_RETURN ((LM_ERROR, "not enough memory?\n"), -1); return tid; } int Input_Handler::cancel_timer (void *argument) { int id = *(int *) argument; return this->reactor ()->cancel_timer (id); } int Input_Handler::shutdown_timer (void *) { this->done_ = 1; ACE_DEBUG ((LM_DEBUG, "Shutting down event loop\n")); return -1; } int Input_Handler::list_timer (void *) { ACE_Timer_Queue_Iterator &iter = this->tq_->iter (); ACE_DEBUG ((LM_DEBUG, "\n\nTimers in queue:\n")); for (; !iter.isdone (); iter.next ()) { ACE_Timer_Node *tn = iter.item (); ACE_DEBUG ((LM_DEBUG, "Timer #%d: %d.%06d\n", tn->get_timer_id (), tn->get_timer_value ().sec (), tn->get_timer_value ().usec ())); } return 0; } int Input_Handler::handle_input (ACE_HANDLE) { return driver_.get_next_request (); } Reactor_Timer_Queue_Test_Driver::Reactor_Timer_Queue_Test_Driver (void) : thandler_ (&timer_queue_, *this) { } Reactor_Timer_Queue_Test_Driver::~Reactor_Timer_Queue_Test_Driver (void) { // unhook our timer queue ACE_Reactor::instance ()->timer_queue (0); } int Reactor_Timer_Queue_Test_Driver::display_menu (void) { static char menu[] = "\n*****\n" "1) Schedule timer \n" "2) Cancel timer \n" "3) List all timers\n" "4) Shutdown program\n" "Enter selection:"; ACE_DEBUG ((LM_DEBUG, "%s", menu)); return 0; } int Reactor_Timer_Queue_Test_Driver::init (void) { typedef Command CMD; // initialize s with their corresponding methods. ACE_NEW_RETURN (schedule_cmd_, CMD (thandler_, &Input_Handler::schedule_timer), -1); ACE_NEW_RETURN (cancel_cmd_, CMD (thandler_, &Input_Handler::cancel_timer), -1); ACE_NEW_RETURN (list_cmd_, CMD (thandler_, &Input_Handler::list_timer), -1); ACE_NEW_RETURN (shutdown_cmd_, CMD (thandler_, &Input_Handler::shutdown_timer), -1); ACE_Reactor::instance ()->timer_queue (&timer_queue_); ACE_Event_Handler::register_stdin_handler (&thandler_, ACE_Reactor::instance (), ACE_Thread_Manager::instance ()); // print the menu of options. this->display_menu (); return 0; } // run test was overrun due to the reactive way of handling input. int Reactor_Timer_Queue_Test_Driver::run_test (void) { ACE_DEBUG ((LM_DEBUG, "TIMER TEST STARTED\n")); this->init (); // Run until we say stop. while (thandler_.done () == 0) ACE_Reactor::instance ()->handle_events (); ACE_DEBUG ((LM_DEBUG, "TIMER TEST ENDED\n")); return 0; }