summaryrefslogtreecommitdiff
path: root/examples/Timer_Queue
diff options
context:
space:
mode:
authorschmidt <douglascraigschmidt@users.noreply.github.com>1997-10-12 18:11:50 +0000
committerschmidt <douglascraigschmidt@users.noreply.github.com>1997-10-12 18:11:50 +0000
commitd97e343634a25cb8148fa2bafbe9a10ec7e4dbd1 (patch)
tree143b17139aa547ff002f20d4c6847cab57f79e00 /examples/Timer_Queue
parent12b4694c6e80d75a53fbd96d7da87de1f9b0cf0d (diff)
downloadATCD-d97e343634a25cb8148fa2bafbe9a10ec7e4dbd1.tar.gz
*** empty log message ***
Diffstat (limited to 'examples/Timer_Queue')
-rw-r--r--examples/Timer_Queue/Async_Timer_Queue_Test.cpp14
-rw-r--r--examples/Timer_Queue/Makefile5
-rw-r--r--examples/Timer_Queue/README34
-rw-r--r--examples/Timer_Queue/Thread_Timer_Queue_Test.cpp306
4 files changed, 336 insertions, 23 deletions
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 &current_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 &current_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 */