diff options
author | schmidt <douglascraigschmidt@users.noreply.github.com> | 1997-10-12 18:11:50 +0000 |
---|---|---|
committer | schmidt <douglascraigschmidt@users.noreply.github.com> | 1997-10-12 18:11:50 +0000 |
commit | d97e343634a25cb8148fa2bafbe9a10ec7e4dbd1 (patch) | |
tree | 143b17139aa547ff002f20d4c6847cab57f79e00 /examples | |
parent | 12b4694c6e80d75a53fbd96d7da87de1f9b0cf0d (diff) | |
download | ATCD-d97e343634a25cb8148fa2bafbe9a10ec7e4dbd1.tar.gz |
*** empty log message ***
Diffstat (limited to 'examples')
-rw-r--r-- | examples/Makefile | 1 | ||||
-rw-r--r-- | examples/Timer_Queue/Async_Timer_Queue_Test.cpp | 14 | ||||
-rw-r--r-- | examples/Timer_Queue/Makefile | 5 | ||||
-rw-r--r-- | examples/Timer_Queue/README | 34 | ||||
-rw-r--r-- | examples/Timer_Queue/Thread_Timer_Queue_Test.cpp | 306 |
5 files changed, 337 insertions, 23 deletions
diff --git a/examples/Makefile b/examples/Makefile index 2b6289668a7..73c7088a98c 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -23,6 +23,7 @@ DIRS = ASX \ Shared_Malloc \ Shared_Memory \ System_V_IPC \ + Timer_Queue \ Threads # Makefiles TBD: diff --git a/examples/Timer_Queue/Async_Timer_Queue_Test.cpp b/examples/Timer_Queue/Async_Timer_Queue_Test.cpp index 12a23e6a887..5d4aa6004eb 100644 --- a/examples/Timer_Queue/Async_Timer_Queue_Test.cpp +++ b/examples/Timer_Queue/Async_Timer_Queue_Test.cpp @@ -10,7 +10,7 @@ // // = DESCRIPTION // This test exercises the <ACE_Asynch_Timer_Queue_Adapter> -// using an <ACE_Timer_List>. +// using an <ACE_Timer_Heap>. // // = AUTHORS // Douglas C. Schmidt @@ -18,7 +18,7 @@ // ============================================================================ #include "ace/Signal.h" -#include "ace/Timer_List.h" +#include "ace/Timer_Heap.h" class Timer_Handler : public ACE_Event_Handler // = TITLE @@ -77,8 +77,8 @@ private: static Async_Timer_Queue *instance_; // Pointer to the timer queue. - ACE_Async_Timer_Queue_Adapter<ACE_Timer_List> tq_; - // The adapter is instantiated by an <ACE_Timer_List>. + ACE_Async_Timer_Queue_Adapter<ACE_Timer_Heap> tq_; + // The adapter is instantiated by an <ACE_Timer_Heap>. }; // Initialize the Singleton pointer. @@ -119,7 +119,7 @@ Async_Timer_Queue::dump (void) // This iterator is implicitly protected since SIGINT and SIGALRM // signals cannot occur while it is running. - for (ACE_Timer_List_Iterator iter (this->tq_.timer_queue ()); + for (ACE_Timer_Heap_Iterator iter (this->tq_.timer_queue ()); iter.item () != 0; iter.next ()) iter.item ()->dump (); @@ -278,7 +278,7 @@ main (int, char *[]) } #if defined (ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION) -template class ACE_Async_Timer_Queue_Adapter<ACE_Timer_List>; +template class ACE_Async_Timer_Queue_Adapter<ACE_Timer_Heap>; #elif defined (ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA) -#pragma instantiate ACE_Async_Timer_Queue_Adapter<ACE_Timer_List> +#pragma instantiate ACE_Async_Timer_Queue_Adapter<ACE_Timer_Heap> #endif /* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION */ diff --git a/examples/Timer_Queue/Makefile b/examples/Timer_Queue/Makefile index a0220295935..11255f0752c 100644 --- a/examples/Timer_Queue/Makefile +++ b/examples/Timer_Queue/Makefile @@ -8,8 +8,9 @@ INFO = README -BIN = Reactor_Timer_Queue_Test \ - Async_Timer_Queue_Test +BIN = Async_Timer_Queue_Test \ + Reactor_Timer_Queue_Test \ + Thread_Timer_Queue_Test SRC = $(addsuffix .cpp,$(BIN)) OBJ = $(SRC:%.cpp=$(VDIR)%.o) diff --git a/examples/Timer_Queue/README b/examples/Timer_Queue/README index 90b8324225a..f09ee4d45cc 100644 --- a/examples/Timer_Queue/README +++ b/examples/Timer_Queue/README @@ -1,19 +1,25 @@ -This directory contains two examples: <Async_Timer_Queue_Test> and -<Reactor_Timer_Queue_Test>. They show how you can use various -mechanisms to schedule and handle time events. Both programs are -interactive. You can schedule or cancel time events and list all the -timers that are waiting to be triggered. - -Async_Timer_Queue_Test: ------------------------ - -This example shows how to use singals as the mechanism to generate -time events. (Notice that this example doesn't work on NT because of -NT's limited signal mechanism.) +This directory contains several examples that illustrate how to use +various concurrency mechanisms to schedule and handle timer-based +events. All programs are interactive. You can schedule or cancel +time events and list all the timers that are waiting to be triggered. +The tests include: Reactor_Timer_Queue_Test: ------------------------- -This example shows how to use ACE_Reactor as the time events -generating mechanism.
\ No newline at end of file +This example shows how to use ACE_Reactor as the timer queue +management mechanism. + +Thread_Timer_Queue_Test: +------------------------ + +This example shows how to use threads as the mechanism to generate +timer queue events. + +Async_Timer_Queue_Test: +----------------------- + +This example shows how to use singals as the mechanism to generate +timer queue events. It doesn't work on NT because of NT's limited +signal mechanism, i.e., no support for SIGALRM. diff --git a/examples/Timer_Queue/Thread_Timer_Queue_Test.cpp b/examples/Timer_Queue/Thread_Timer_Queue_Test.cpp new file mode 100644 index 00000000000..d07074544f9 --- /dev/null +++ b/examples/Timer_Queue/Thread_Timer_Queue_Test.cpp @@ -0,0 +1,306 @@ +// $Id$ + +// ============================================================================ +// +// = LIBRARY +// examples +// +// = FILENAME +// Thread_Timer_Queue_Test.cpp +// +// = DESCRIPTION +// This test exercises the <ACE_Thread_Timer_Queue_Adapter> +// using an <ACE_Timer_Heap>. +// +// = AUTHORS +// Carlos O'Ryan and Douglas C. Schmidt +// +// ============================================================================ + +#include "ace/Task.h" +#include "ace/Timer_Heap_T.h" + +// These typedefs ensure that we use the minimal amount of locking +// necessary. +typedef ACE_Event_Handler_Handle_Timeout_Upcall<ACE_Null_Mutex> + Upcall; +typedef ACE_Timer_Heap_T<ACE_Event_Handler *, + ACE_Event_Handler_Handle_Timeout_Upcall<ACE_Null_Mutex>, + ACE_Null_Mutex> + Timer_Heap; +typedef ACE_Timer_Heap_Iterator_T<ACE_Event_Handler *, + ACE_Event_Handler_Handle_Timeout_Upcall<ACE_Null_Mutex>, + ACE_Null_Mutex> + Timer_Heap_Iterator; +typedef Thread_Timer_Queue_Adapter<Timer_Heap> + Thread_Timer_Queue; + +class Handler : public ACE_Event_Handler + // = TITLE + // This class implements a simple Event_Handler, + // + // = DESCRIPTION + // The <handle_timeout> hook method justs printouts the current + // time, delete this and prints the delay on the twhen it is + // expired. +{ +public: + Handler (const ACE_Time_Value &expiration_time); + ~Handler (void); + + void set_id (int id); + // Store an "id" for the Handler, which is only use to print better + // messages. + + virtual int handle_timeout (const ACE_Time_Value ¤t_time, + const void *arg); + // Call back hook. + virtual int cancelled (void); + +private: + int id_; + // Store an "id" for the Handler, which is only use to print better + // messages. +}; + +class Input_Task : public ACE_Task<ACE_SYNCH> + // = TITLE + // Read user actions on the Timer_Queue from stdin. + // + // = DESCRIPTION + // This class reads user input from stdin; those commands permit the + // control of a Timer_Queue, which is dispatched by another thread. +{ +public: + Input_Task (Thread_Timer_Queue* queue); + + virtual int svc (void); + // The method run on the new thread. + +private: + // Some helper methods. + void usage (void) const; + int add_timer (u_long seconds); + void cancel_timer (int id); + int parse_commands (const char *buffer); + void dump (void); + +private: + Thread_Timer_Queue *queue_; + + const int usecs_; +}; + +// Administrivia methods... +Handler::Handler(const ACE_Time_Value& expiration_time) + : expires(expiration_time), + id(0) +{ +} + +Handler::~Handler() +{ +} + +void +Handler::set_id (int id) +{ + id_ = id; +} + +// This is the method invoked when the Timer expires. + +int +Handler::handle_timeout(const ACE_Time_Value ¤t_time, + const void*) +{ + ACE_Time_Value delay = current_time - expires; + + // No need to protect this printf is always called from a Async safe + // point. + ACE_OS::printf ("\nexpiring timer %d at %u.%07.7u secs\n" + "\tthere was a %u.%07.7u secs delay\n", + id, current_time.sec (), current_time.usec (), + delay.sec (), delay.usec ()); + + // Notice this delete is protected. + delete this; + return 0; +} + +// The handler was cancelled, so we must delete this. + +int +Handler::cancelled (void) +{ + delete this; + return 0; +} + +Input_Task::Input_Task (Thread_Timer_Queue *queue) + : queue_ (queue), + usecs_ (1000000) // @@ Make this an ACE #define constant? +{ +} + +int +Input_Task::svc (void) +{ + for (;;) + { + char buf[BUFSIZ]; + + ACE_OS::printf ("please enter your choice: "); + ACE_OS::fflush (stdout); + + if (ACE_OS::read (ACE_STDIN, buf, sizeof buf) <= 0) + break; + + if (parse_commands (buf) < 0) + break; + } + + this->queue_->deactivate (); + ACE_DEBUG ((LM_DEBUG, "terminating input thread\n")); + return 0; +} + +int +Input_Task::add_timer (u_long useconds) +{ + ACE_Time_Value interval (useconds / usecs_, useconds % usecs_); + ACE_Time_Value expire_at = ACE_OS::gettimeofday () + interval; + + Handler *h; + + ACE_NEW_RETURN (h, Handler (expire_at)); + + int id = queue_->schedule (h, 0, expire_at); + + if (id == -1) + ACE_ERROR_RETURN ((LM_ERROR, "schedule failed"), -1); + + // We store the id into the handler, this is only used to produce + // nicer messages. + // @@ Should this be something that a user can extract? + h->set_id (id); + + ACE_OS::printf ("scheduling timer %d\n", id); + return 0; +} + +void +Input_Task::cancel_timer (int id) +{ + this->queue_->cancel (id); +} + +void +Input_Task::dump (void) +{ + ACE_GUARD (ACE_SYNCH_MUTEX, ace_mon, this->queue_->lock ()); + + ACE_DEBUG ((LM_DEBUG, "begin dumping timer queue\n")); + + for (Timer_Heap_Iterator i (this->queue_->timer_queue ()); + i.item () != 0; + i.next ()) + i.item ()->dump (); + + ACE_DEBUG ((LM_DEBUG, "end dumping timer queue\n")); +} + +void +Input_Task::usage (void) const +{ + ACE_OS::printf ("Usage:\n" + "1 <microseconds>: setups a new timer\n" + "2 <timerid>: removes a timer\n" + "3 : prints timer queue\n" + "4 : exit\n"); +} + +int +Input_Task::parse_commands (const char *buf) +{ + int option; + + if (::sscanf (buf, "%d", &option) <= 0) + { + // If there was an error reading the option simply print thge + // usage and try on the next line. + this->usage (); + return 0; + } + + switch (option) + { + case 1: // Install a new timer. + { + u_long useconds; + // We just reread the option, this simplies parsing (since + // sscanf can do it for us.) + if (::sscanf (buf, "%d %lu", &option, &useconds) < 2) + { + this->usage (); + return 0; + } + if (this->add_timer (useconds) == -1) + ACE_ERROR_RETURN ((LM_ERROR, "%t %p\n", "new timer failed"), -1); + } + break; // Cancel an existing timer. + case 2: + { + u_long id; + // We just reread the option, this simplies parsing (since + // sscanf can do it for us.) + if (::sscanf (buf, "%d %lu", &option, &id) < 2) + { + this->usage (); + return 0; + } + this->cancel_timer (id); + } + break; + + case 3: // Dump the existing timers. + this->dump (); + break; + + case 4: // Exit the program. + return -1; + break; + + default: + this->usage (); + break; + } + return 0; +} + +int +main (int argc, char* argv[]) +{ + Thread_Timer_Queue tq; + + Input_Task input_task (&tq); + + if (input_task.activate () == -1) + ACE_ERROR_RETURN ((LM_ERROR, "cannot activate input task"), -1); + + if (tq.activate () == -1) + ACE_ERROR_RETURN ((LM_ERROR, "cannot activate timer queue"), -1); + + if (ACE_Thread_Manager::instance ()->wait () == -1) + ACE_ERROR_RETURN ((LM_ERROR, "wait on Thread_Manager failed"),-1); + + return 0; +} + +// @@ Add template specializations. + +#if defined (ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION) +template class ACE_Thread_Timer_Queue_Adapter<ACE_Timer_Heap>; +#elif defined (ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA) +#pragma instantiate ACE_Thread_Timer_Queue_Adapter<ACE_Timer_Heap> +#endif /* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION */ |