summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog-97a42
-rw-r--r--ace/Asynch_IO.cpp11
-rw-r--r--ace/Asynch_IO.h12
-rw-r--r--ace/Proactor.cpp312
-rw-r--r--ace/Proactor.h96
-rw-r--r--ace/Strategies.cpp8
-rw-r--r--ace/Strategies.h18
-rw-r--r--ace/Timer_Heap.cpp25
-rw-r--r--ace/Timer_Heap.h6
-rw-r--r--ace/Timer_List.cpp6
-rw-r--r--ace/Timer_List.h5
-rw-r--r--ace/Timer_Queue.cpp37
-rw-r--r--ace/Timer_Queue.h24
-rw-r--r--examples/Reactor/Proactor/test_proactor.mak247
-rw-r--r--examples/Reactor/Proactor/test_proactor.mdpbin46592 -> 54784 bytes
-rw-r--r--examples/Reactor/Proactor/test_timeout.cpp92
16 files changed, 855 insertions, 86 deletions
diff --git a/ChangeLog-97a b/ChangeLog-97a
index a456477d6dc..0c151ef6bb9 100644
--- a/ChangeLog-97a
+++ b/ChangeLog-97a
@@ -1,3 +1,45 @@
+Tue Apr 22 01:38:14 1997 <irfan@TWOSTEP>
+
+ * ace/Timer_Queue: Added ACE_Upcall_Strategy as a parameter to the
+ constructor. <expire> will call <upcall_strategy->upcall> if
+ <upcall_strategy> is not 0. Else it will call <handle_timeout>
+ on the <Event_Handler>. Thus ACE_Upcall_Strategy becomes a
+ vehicle for extending the behavior of ACE_Timer_Queue wrt the
+ upcall (callback) *without subclassing*. Hence, it's an example
+ of the Bridge/Strategy patterns.
+
+ This also affected ACE_Timer_List and ACE_Timer_Heap
+
+ * ace/Strategies: Added ACE_Upcall_Strategy.
+
+ * ace/Proactor: Added timing support to the <handle_event> calls.
+
+ * ace/Asynch_IO: ACE_Handler now supports handle_timeout.
+
+ * ace/Proactor: Added timer support for the new Proactor. This
+ new scheme allows any of the threads in the "thread pool"
+ waiting on the completion port of the Proactor to execute the
+ callback routine of the handler.
+
+ The implementation included adding ACE_Proactor_Timer_Handler
+ class that has a thread that will wait on the earliest time in a
+ timer queue and an event. When a timer expires, the thread will
+ post a completion event on the port and go back to waiting on
+ the timer queue and event. If the event is signaled, the thread
+ will refresh the time it is currently waiting on (in case the
+ earliest time has changed).
+
+ The ACE_Proactor::Asynch_Timer class is posted to the completion
+ port when a timer expires. When the <complete> method of this
+ object is called, the <handler>'s handle_timeout method will be
+ called.
+
+ * examples/Reactor/Proactor/test_timeout: This example illustrates
+ the new timer features in the Proactor
+
+ * examples/Reactor/Proactor/test_proactor.{mdp,mak}: Added new
+ example.
+
Tue Apr 22 00:21:03 1997 Douglas C. Schmidt <schmidt@tango.cs.wustl.edu>
* examples/OS/Process/process.cpp (main): Replaced the use of
diff --git a/ace/Asynch_IO.cpp b/ace/Asynch_IO.cpp
index 067810f139e..1e0cb04ba4e 100644
--- a/ace/Asynch_IO.cpp
+++ b/ace/Asynch_IO.cpp
@@ -35,6 +35,10 @@ ACE_Asynch_Result::ACE_Asynch_Result (ACE_Handler &handler,
this->hEvent = event;
}
+ACE_Asynch_Result::~ACE_Asynch_Result (void)
+{
+}
+
u_long
ACE_Asynch_Result::bytes_transferred (void) const
{
@@ -945,12 +949,13 @@ void
ACE_Handler::handle_notify (const ACE_Asynch_Notify::Result &result)
{
}
+*/
-void
-ACE_Handler::handle_timeout (const ACE_Asynch_Timeout::Result &result)
+void
+ACE_Handler::handle_timeout (const ACE_Time_Value &tv,
+ const void *act)
{
}
-*/
ACE_Proactor *
ACE_Handler::proactor (void)
diff --git a/ace/Asynch_IO.h b/ace/Asynch_IO.h
index b0fcd522070..3145d3104c1 100644
--- a/ace/Asynch_IO.h
+++ b/ace/Asynch_IO.h
@@ -87,6 +87,9 @@ public:
u_long offset_high = 0);
// Constructor
+ virtual ~ACE_Asynch_Result (void);
+ // Destructor
+
protected:
virtual void complete (u_long bytes_transferred,
int success,
@@ -814,8 +817,13 @@ public:
/*
virtual void handle_notify (const ACE_Asynch_Notify::Result &result);
- virtual void handle_timeout (const ACE_Asynch_Timeout::Result &result);
- */
+ */
+
+ virtual void handle_timeout (const ACE_Time_Value &tv,
+ const void *act = 0);
+ // Called when timer expires.
+ // <tv> was the requested time value and
+ // <act> is the ACT passed when scheduling the timer
ACE_Proactor *proactor (void);
// Get the proactor associated with this handler.
diff --git a/ace/Proactor.cpp b/ace/Proactor.cpp
index 7a76cfa55f8..c7bf5f60089 100644
--- a/ace/Proactor.cpp
+++ b/ace/Proactor.cpp
@@ -7,10 +7,68 @@
#if defined (ACE_WIN32)
// This only works on Win32 platforms
+#include "ace/Task.h"
#include "ace/Timer_Queue.h"
+#include "ace/Timer_List.h"
#include "ace/Log_Msg.h"
-#include "ace/Asynch_IO.h"
+class ACE_Export ACE_Proactor_Timer_Handler : public ACE_Task <ACE_NULL_SYNCH>
+ //
+ // = TITLE
+ //
+ // A Handler for timer. It helps in the management of timers
+ // registered with the Proactor.
+ //
+ // = DESCRIPTION
+ //
+ // This object has a thread that will wait on the earliest
+ // time in a list of timers and an event. When a timer
+ // expires, the thread will post a completion event on the
+ // port and go back to waiting on the timer queue and
+ // event. If the event is signaled, the thread will refresh
+ // the time it is currently waiting on (in case the earliest
+ // time has changed)
+ //
+{
+ friend class ACE_Proactor;
+ // Proactor has special privileges
+
+public:
+ ACE_Proactor_Timer_Handler (ACE_Proactor &proactor);
+
+protected:
+ virtual int svc (void);
+ // Run by a daemon thread to handle deferred processing. In other
+ // words, this method will do the waiting on the earliest timer
+ // and event
+
+ virtual int handle_timeout (const ACE_Time_Value &tv,
+ const void *arg = 0);
+ // Framework calls this when a timer expires
+
+ ACE_Auto_Event timer_event_;
+ // Event to wait on
+
+ ACE_Proactor &proactor_;
+ // Proactor
+
+public:
+ class ACE_Export ACT
+ //
+ // = TITLE
+ //
+ // A new ACT that combines the old ACT and Handler
+ //
+ {
+ public:
+ ACT (ACE_Handler &handler,
+ const void *act);
+
+ ACE_Handler &handler_;
+ const void *act_;
+ };
+};
+
#if !defined (__ACE_INLINE__)
#include "ace/Proactor.i"
#endif /* __ACE_INLINE__ */
@@ -18,14 +76,27 @@
ACE_Proactor::ACE_Proactor (size_t number_of_threads,
ACE_Timer_Queue *tq)
: completion_port_ (0), // This *MUST* be 0, *NOT* ACE_INVALID_HANDLE!!!!
- number_of_threads_ (number_of_threads)
+ number_of_threads_ (number_of_threads),
+ timer_queue_ (0),
+ delete_timer_queue_ (0),
+ timer_handler_ (0)
{
+ ACE_NEW (this->timer_handler_, ACE_Proactor_Timer_Handler (*this));
+
+ // set the timer queue
+ this->timer_queue (tq);
+
+ // create the completion port
this->completion_port_ = ::CreateIoCompletionPort (INVALID_HANDLE_VALUE,
this->completion_port_,
0,
this->number_of_threads_);
if (this->completion_port_ == 0)
ACE_ERROR ((LM_ERROR, "%p\n", "CreateIoCompletionPort"));
+
+ // activate <timer_handler>
+ if (this->timer_handler_->activate () == -1)
+ ACE_ERROR ((LM_ERROR, "%p Could not create thread\n", "Task::activate"));
}
ACE_Proactor::~ACE_Proactor (void)
@@ -36,6 +107,21 @@ ACE_Proactor::~ACE_Proactor (void)
int
ACE_Proactor::close (void)
{
+ // Take care of the timer handler
+ if (this->timer_handler_)
+ {
+ delete this->timer_handler_;
+ this->timer_handler_ = 0;
+ }
+
+ // Take care of the timer queue
+ if (this->delete_timer_queue_)
+ {
+ delete this->timer_queue_;
+ this->timer_queue_ = 0;
+ this->delete_timer_queue_ = 0;
+ }
+
// Close the completion port
if (this->completion_port_ != 0)
{
@@ -68,14 +154,87 @@ ACE_Proactor::register_handle (ACE_HANDLE handle,
}
int
+ACE_Proactor::schedule_timer (ACE_Handler &handler,
+ const void *act,
+ const ACE_Time_Value &time)
+{
+ return this->schedule_timer (handler, act, time, ACE_Time_Value::zero);
+}
+
+int
+ACE_Proactor::schedule_repeating_timer (ACE_Handler &handler,
+ const void *act,
+ const ACE_Time_Value &interval)
+{
+ return this->schedule_timer (handler, act, interval, interval);
+}
+
+int
+ACE_Proactor::schedule_timer (ACE_Handler &handler,
+ const void *act,
+ const ACE_Time_Value &time,
+ const ACE_Time_Value &interval)
+{
+ // Create a new ACT
+ ACE_Proactor_Timer_Handler::ACT *new_act = 0;
+ ACE_NEW_RETURN (new_act, ACE_Proactor_Timer_Handler::ACT (handler, act), -1);
+
+ // Only one guy goes in here at a time
+ ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon, this->timer_queue_->lock (), -1);
+
+ // absolute time
+ ACE_Time_Value absolute_time = this->timer_queue_->gettimeofday () + time;
+
+ // Schedule the timer
+ int result = this->timer_queue_->schedule (this->timer_handler_,
+ new_act,
+ absolute_time,
+ interval);
+ // Failure of schedule
+ if (result == -1)
+ // cleanup
+ delete new_act;
+
+ // no failures: check to see if we are the earliest time
+ else if (this->timer_queue_->earliest_time () == absolute_time)
+ // wake up the timer thread
+ if (this->timer_handler_->timer_event_.signal () == -1)
+ {
+ // failure: cleanup
+ delete new_act;
+ // Cancel timer
+ this->timer_queue_->cancel (result);
+ result = -1;
+ }
+ return result;
+}
+
+int
+ACE_Proactor::cancel_timer (int timer_id,
+ const void **arg)
+{
+ // No need to singal timer event here. Even if the cancel timer was
+ // the earliest, we will have an extra wakeup.
+ return this->timer_queue_->cancel (timer_id, arg);
+}
+
+int
ACE_Proactor::handle_events (ACE_Time_Value &wait_time)
{
- return 0;
+ // Decrement <wait_time> with the amount of time spent in the method
+ ACE_Countdown_Time countdown (&wait_time);
+ return this->handle_events (wait_time.msec ());
}
int
ACE_Proactor::handle_events (void)
{
+ return this->handle_events (INFINITE);
+}
+
+int
+ACE_Proactor::handle_events (unsigned long milli_seconds)
+{
OVERLAPPED *overlapped = 0;
u_long bytes_transferred = 0;
u_long completion_key = 0;
@@ -85,11 +244,20 @@ ACE_Proactor::handle_events (void)
&bytes_transferred,
&completion_key,
&overlapped,
- INFINITE);
-
+ milli_seconds);
if (result == FALSE && overlapped == 0)
- ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "GetQueuedCompletionStatus"), -1);
+ {
+ errno = ::GetLastError ();
+ // @@ What's the WIN32 constant for timeout (258)?!?!?!
+ if (errno == 258)
+ {
+ errno = ETIMEDOUT;
+ return 0;
+ }
+ else
+ ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "GetQueuedCompletionStatus"), -1);
+ }
else
{
// Narrow result
@@ -177,4 +345,136 @@ ACE_Proactor::number_of_threads (size_t threads)
this->number_of_threads_ = threads;
}
+ACE_Timer_Queue *
+ACE_Proactor::timer_queue (void) const
+{
+ return this->timer_queue_;
+}
+
+void
+ACE_Proactor::timer_queue (ACE_Timer_Queue *tq)
+{
+ // cleanup old timer queue
+ if (this->delete_timer_queue_)
+ {
+ delete this->timer_queue_;
+ this->delete_timer_queue_ = 0;
+ }
+
+ // new timer queue
+ if (tq == 0)
+ {
+ this->timer_queue_ = new ACE_Timer_List;
+ this->delete_timer_queue_ = 1;
+ }
+ else
+ {
+ this->timer_queue_ = tq;
+ this->delete_timer_queue_ = 0;
+ }
+}
+
+ACE_Proactor_Timer_Handler::ACE_Proactor_Timer_Handler (ACE_Proactor &proactor)
+ : proactor_ (proactor),
+ ACE_Task <ACE_NULL_SYNCH> (&proactor.thr_mgr_)
+{
+}
+
+int
+ACE_Proactor_Timer_Handler::svc (void)
+{
+ u_long time;
+ ACE_Time_Value absolute_time;
+
+ for (;;)
+ {
+ // default value
+ time = INFINITE;
+
+ // If the timer queue is not empty
+ if (!this->proactor_.timer_queue_->is_empty ())
+ {
+ // Get the earliest absolute time
+ absolute_time
+ = this->proactor_.timer_queue_->earliest_time ()
+ - this->proactor_.timer_queue_->gettimeofday ();
+
+ // time to wait
+ time = absolute_time.msec ();
+
+ // Make sure the time is positive
+ if (time < 0)
+ time = 0;
+ }
+
+ // Wait for event upto <time> milli seconds
+ int result = ::WaitForSingleObject (this->timer_event_.handle (),
+ time);
+ switch (result)
+ {
+ case WAIT_TIMEOUT:
+ // timeout: expire timers
+ this->proactor_.timer_queue_->expire ();
+ break;
+ case WAIT_FAILED:
+ // error
+ ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "WaitForSingleObject"), -1);
+ }
+ }
+
+ return 0;
+}
+
+int
+ACE_Proactor_Timer_Handler::handle_timeout (const ACE_Time_Value &tv,
+ const void *arg)
+{
+ ACE_Proactor_Timer_Handler::ACT *new_act
+ = (ACE_Proactor_Timer_Handler::ACT *) arg;
+
+ // Create the Asynch_Timer
+ ACE_Proactor::Asynch_Timer *asynch_timer
+ = new ACE_Proactor::Asynch_Timer (new_act->handler_,
+ new_act->act_,
+ tv);
+
+ // Post a completion
+ if (::PostQueuedCompletionStatus (this->proactor_.completion_port_, // completion port
+ 0, // number of bytes tranferred
+ 0, // completion key
+ asynch_timer // overlapped
+ ) == FALSE)
+ {
+ ACE_ERROR ((LM_ERROR, "Failure in dealing with timers: PostQueuedCompletionStatus failed"));
+ delete asynch_timer;
+ }
+
+ return 0;
+}
+
+ACE_Proactor::Asynch_Timer::Asynch_Timer (ACE_Handler &handler,
+ const void *act,
+ const ACE_Time_Value &tv)
+ : ACE_Asynch_Result (handler,
+ act),
+ time_ (tv)
+{
+}
+
+void
+ACE_Proactor::Asynch_Timer::complete (u_long bytes_transferred,
+ int success,
+ const void *completion_key,
+ u_long error)
+{
+ this->handler_.handle_timeout (this->time_, this->act ());
+}
+
+ACE_Proactor_Timer_Handler::ACT::ACT (ACE_Handler &handler,
+ const void *act)
+ : act_ (act),
+ handler_ (handler)
+{
+}
+
#endif /* ACE_WIN32 */
diff --git a/ace/Proactor.h b/ace/Proactor.h
index 79a0d8d8600..205844e6260 100644
--- a/ace/Proactor.h
+++ b/ace/Proactor.h
@@ -18,13 +18,15 @@
#if !defined (ACE_PROACTOR_H)
#define ACE_PROACTOR_H
-#include "ace/OS.h"
+#include "ace/Asynch_IO.h"
+#include "ace/Thread_Manager.h"
#if defined (ACE_WIN32)
// This only works on Win32 platforms
class ACE_Timer_Queue;
class ACE_Asynch_Result;
+class ACE_Proactor_Timer_Handler;
class ACE_Export ACE_Proactor
//
@@ -36,6 +38,9 @@ class ACE_Export ACE_Proactor
//
// A manager for the I/O completion port.
{
+ friend class ACE_Proactor_Timer_Handler;
+ // Timer Handler has special privileges
+
public:
ACE_Proactor (size_t number_of_threads = 0,
ACE_Timer_Queue *tq = 0);
@@ -51,6 +56,44 @@ public:
const void *completion_key);
// This method adds the <handle> to the I/O completion port
+ // = Timer management.
+ virtual int schedule_timer (ACE_Handler &handler,
+ const void *act,
+ const ACE_Time_Value &time);
+ // Schedule a <handler> that will expire after <time>. If it
+ // expires then <act> is passed in as the value to the <handler>'s
+ // <handle_timeout> callback method. This method returns a
+ // <timer_id>. This <timer_id> can be used to cancel a timer before
+ // it expires. The cancellation ensures that <timer_ids> are unique
+ // up to values of greater than 2 billion timers. As long as timers
+ // don't stay around longer than this there should be no problems
+ // with accidentally deleting the wrong timer. Returns -1 on
+ // failure (which is guaranteed never to be a valid <timer_id>.
+
+ virtual int schedule_repeating_timer (ACE_Handler &handler,
+ const void *act,
+ const ACE_Time_Value &interval);
+
+ // Same as above except <interval> it is used to reschedule the
+ // <handler> automatically.
+
+ int schedule_timer (ACE_Handler &handler,
+ const void *act,
+ const ACE_Time_Value &time,
+ const ACE_Time_Value &interval);
+ // This combines the above two methods into one. Mostly for backward
+ // compatibility.
+
+ virtual int cancel_timer (int timer_id,
+ const void **act = 0);
+ // Cancel the single <ACE_Handler> that matches the <timer_id> value
+ // (which was returned from the <schedule> method). If <act> is
+ // non-NULL then it will be set to point to the ``magic cookie''
+ // argument passed in when the <Handler> was registered. This makes
+ // it possible to free up the memory and avoid memory leaks.
+ // Returns 1 if cancellation succeeded and 0 if the <timer_id>
+ // wasn't found.
+
virtual int handle_events (ACE_Time_Value &wait_time);
// Dispatch a single set of events. If <wait_time> elapses before
// any events occur, return.
@@ -83,6 +126,10 @@ public:
void number_of_threads (size_t threads);
// Number of thread used as a parameter to CreatIoCompletionPort
+ ACE_Timer_Queue *timer_queue (void) const;
+ void timer_queue (ACE_Timer_Queue *);
+ // Get/Set timer queue
+
protected:
void application_specific_code (ACE_Asynch_Result *asynch_result,
@@ -93,8 +140,55 @@ protected:
// Protect against structured exceptions caused by user code when
// dispatching handles
+ virtual int handle_events (unsigned long milli_seconds);
+ // Dispatch a single set of events. If <milli_seconds> elapses
+ // before any events occur, return.
+
+ class ACE_Export Asynch_Timer : protected ACE_Asynch_Result
+ //
+ // = TITLE
+ //
+ // This class is posted to the completion port when a timer
+ // expires. When the complete method of this object is called,
+ // the <handler>'s handle_timeout method will be called.
+ //
+ {
+ friend class ACE_Proactor_Timer_Handler;
+ // Timer Handler has special privileges
+
+ public:
+ Asynch_Timer (ACE_Handler &handler,
+ const void *act,
+ const ACE_Time_Value &tv);
+
+ protected:
+ virtual void complete (u_long bytes_transferred,
+ int success,
+ const void *completion_key,
+ u_long error = 0);
+ // This method calls the <handler>'s handle_timeout method
+
+ ACE_Time_Value time_;
+ // Time value requested by caller
+ };
+
ACE_HANDLE completion_port_;
+ // Handle for the completion port
+
size_t number_of_threads_;
+ // This number is passed to the CreatIOCompletionPort() system call
+
+ ACE_Timer_Queue *timer_queue_;
+ // Timer Queue
+
+ int delete_timer_queue_;
+ // Flag on whether to delete the timer queue
+
+ ACE_Proactor_Timer_Handler *timer_handler_;
+ // Handles timeouts events
+
+ ACE_Thread_Manager thr_mgr_;
+ // This will manage the thread in the Timer_Handler
};
#if defined (__ACE_INLINE__)
diff --git a/ace/Strategies.cpp b/ace/Strategies.cpp
index 0943d560b2c..bce6dfc329c 100644
--- a/ace/Strategies.cpp
+++ b/ace/Strategies.cpp
@@ -62,4 +62,12 @@ ACE_ReactorEx_Notification_Strategy::notify (ACE_Event_Handler *eh,
return this->reactorex_->notify (eh, mask);
}
+ACE_Upcall_Strategy::ACE_Upcall_Strategy (void)
+{
+}
+
+ACE_Upcall_Strategy::~ACE_Upcall_Strategy (void)
+{
+}
+
#endif /* ACE_STRATEGIES_C */
diff --git a/ace/Strategies.h b/ace/Strategies.h
index 07fc604be90..087a2e516f6 100644
--- a/ace/Strategies.h
+++ b/ace/Strategies.h
@@ -91,6 +91,24 @@ private:
ACE_ReactorEx *reactorex_;
};
+class ACE_Export ACE_Upcall_Strategy
+ // = TITLE
+ // Abstract class used for defining an upcall (callback)
+ //
+ // = DESCRIPTION
+ // A vehicle for extending the behavior of ACE_Timer_Queue wrt
+ // the upcall (callback) *without subclassing*. Thus, it's an
+ // example of the Bridge/Strategy patterns.
+{
+public:
+ ACE_Upcall_Strategy (void);
+ virtual ~ACE_Upcall_Strategy (void);
+
+ virtual void upcall (ACE_Event_Handler *handler,
+ const void *arg,
+ const ACE_Time_Value &cur_time) = 0;
+};
+
// This needs to come here to avoid circular dependencies.
#include "ace/Strategies_T.h"
diff --git a/ace/Timer_Heap.cpp b/ace/Timer_Heap.cpp
index 97d971d3713..e29ac76565b 100644
--- a/ace/Timer_Heap.cpp
+++ b/ace/Timer_Heap.cpp
@@ -3,6 +3,7 @@
#define ACE_BUILD_DLL
#include "ace/Timer_Heap.h"
+#include "ace/Strategies.h"
ACE_Timer_Heap_Iterator::ACE_Timer_Heap_Iterator (ACE_Timer_Heap &heap)
: timer_heap_ (heap)
@@ -29,8 +30,10 @@ ACE_Timer_Heap_Iterator::next (ACE_Timer_Node *&node,
}
ACE_Timer_Heap::ACE_Timer_Heap (size_t size,
- int preallocate)
- : max_size_ (size),
+ int preallocate,
+ ACE_Upcall_Strategy *upcall_strategy)
+ : ACE_Timer_Queue (upcall_strategy),
+ max_size_ (size),
cur_size_ (0),
iterator_ (*this),
timer_ids_freelist_ (0),
@@ -248,29 +251,27 @@ ACE_Timer_Heap::grow_heap (void)
ACE_NEW (new_timer_ids, int[new_size]);
- ACE_OS::memcpy (new_timer_ids,
- this->timer_ids_,
- max_size_ * sizeof *this->timer_ids_);
+ ACE_OS::memcpy (new_timer_ids, this->timer_ids_, max_size_ * sizeof (int));
delete [] timer_ids_;
this->timer_ids_ = new_timer_ids;
- // Add the new elements to the end of the "freelist"
+ // and add the new elements to the end of the "freelist"
for (size_t i = this->max_size_; i < new_size; i++)
this->timer_ids_[i] = -((int) (i + 1));
// Grow the preallocation array (if using preallocation)
if (this->preallocated_nodes_ != 0)
{
- // Create a new array with max_size elements to link in to
- // existing list.
+ // Create a new array with max_size elements to link in
+ // to existing list.
ACE_NEW (this->preallocated_nodes_,
ACE_Timer_Node[this->max_size_]);
- // Add it to the set for later deletion
+ // add it to the set for later deletion
this->preallocated_node_set_.insert (this->preallocated_nodes_);
- // Link new nodes together (as for original list).
+ // link new nodes together (as for original list)
for (size_t k = 1; k < this->max_size_; k++)
this->preallocated_nodes_[k - 1].next_ =
&this->preallocated_nodes_[k];
@@ -278,7 +279,7 @@ ACE_Timer_Heap::grow_heap (void)
// NULL-terminate the new list.
this->preallocated_nodes_[this->max_size_ - 1].next_ = 0;
- // Link new array to the end of the existling list.
+ // link new array to the end of the existling list
if (this->preallocated_nodes_freelist_ == 0)
this->preallocated_nodes_freelist_ = &preallocated_nodes_[0];
else
@@ -287,7 +288,7 @@ ACE_Timer_Heap::grow_heap (void)
for (ACE_Timer_Node* current = this->preallocated_nodes_freelist_->next_;
current != 0;
- current = current->next_)
+ current = current->next_)
previous = current;
previous->next_ = &this->preallocated_nodes_[0];
diff --git a/ace/Timer_Heap.h b/ace/Timer_Heap.h
index b52d7b0fadd..04c9bb11dd3 100644
--- a/ace/Timer_Heap.h
+++ b/ace/Timer_Heap.h
@@ -47,6 +47,9 @@ protected:
// Pointer to the <ACE_Timer_Heap> that we are iterating over.
};
+// Forward declaration.
+class ACE_Upcall_Strategy;
+
class ACE_Export ACE_Timer_Heap : public ACE_Timer_Queue
// = TITLE
// Provides a very fast and predictable timer implementation.
@@ -65,7 +68,8 @@ class ACE_Export ACE_Timer_Heap : public ACE_Timer_Queue
public:
// = Initialization and termination methods.
ACE_Timer_Heap (size_t size = ACE_DEFAULT_TIMERS,
- int preallocated = 0);
+ int preallocated = 0,
+ ACE_Upcall_Strategy *upcall_strategy = 0);
// The Constructor creates a heap with <size> elements. If
// <preallocated> is non-0 then we'll pre-allocate all the memory
// for the <ACE_Timer_Nodes>. This saves time and is more
diff --git a/ace/Timer_List.cpp b/ace/Timer_List.cpp
index 02773ef5019..75d107d7173 100644
--- a/ace/Timer_List.cpp
+++ b/ace/Timer_List.cpp
@@ -3,6 +3,7 @@
#define ACE_BUILD_DLL
#include "ace/Timer_List.h"
+#include "ace/Strategies.h"
ACE_Timer_List_Iterator::ACE_Timer_List_Iterator (ACE_Timer_List &list)
: timer_list_ (list)
@@ -34,8 +35,9 @@ ACE_Timer_List::iter (void)
// Create an empty list.
-ACE_Timer_List::ACE_Timer_List (void)
- : head_ (0),
+ACE_Timer_List::ACE_Timer_List (ACE_Upcall_Strategy *upcall_strategy)
+ : ACE_Timer_Queue (upcall_strategy),
+ head_ (0),
iterator_ (*this),
timer_id_ (0)
{
diff --git a/ace/Timer_List.h b/ace/Timer_List.h
index 95b4157d215..d4411080746 100644
--- a/ace/Timer_List.h
+++ b/ace/Timer_List.h
@@ -46,6 +46,9 @@ protected:
// Pointer to the <ACE_Timer_List> that we are iterating over.
};
+// Forward declaration.
+class ACE_Upcall_Strategy;
+
class ACE_Export ACE_Timer_List : public ACE_Timer_Queue
// = TITLE
// Provides a simple implementation of timers.
@@ -68,7 +71,7 @@ class ACE_Export ACE_Timer_List : public ACE_Timer_Queue
friend class ACE_Timer_List_Iterator;
public:
// = Initialization and termination methods.
- ACE_Timer_List (void);
+ ACE_Timer_List (ACE_Upcall_Strategy *upcall_strategy = 0);
// Default constructor.
virtual ~ACE_Timer_List (void);
diff --git a/ace/Timer_Queue.cpp b/ace/Timer_Queue.cpp
index b5c9c964d12..e7342315f4d 100644
--- a/ace/Timer_Queue.cpp
+++ b/ace/Timer_Queue.cpp
@@ -3,6 +3,7 @@
#define ACE_BUILD_DLL
#include "ace/Timer_Queue.h"
+#include "ace/Strategies.h"
#if !defined (__ACE_INLINE__)
#include "ace/Timer_Queue.i"
@@ -108,9 +109,10 @@ ACE_Timer_Queue::dump (void) const
ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
}
-ACE_Timer_Queue::ACE_Timer_Queue (void)
+ACE_Timer_Queue::ACE_Timer_Queue (ACE_Upcall_Strategy *upcall_strategy)
: gettimeofday_ (ACE_OS::gettimeofday),
- timer_skew_ (0, ACE_TIMER_SKEW)
+ timer_skew_ (0, ACE_TIMER_SKEW),
+ upcall_strategy_ (upcall_strategy)
{
ACE_TRACE ("ACE_Timer_Queue::ACE_Timer_Queue");
}
@@ -160,9 +162,7 @@ ACE_Timer_Queue::expire (const ACE_Time_Value &cur_time)
reclaim = 0;
}
- // Perform the callback.
- if (handler->handle_timeout (cur_time, arg) == -1)
- this->cancel (handler, 0); // 0 means "call handle_close()".
+ this->upcall (handler, arg, cur_time);
if (reclaim)
// Call the factory method to free up the node.
@@ -174,6 +174,23 @@ ACE_Timer_Queue::expire (const ACE_Time_Value &cur_time)
return number_of_timers_expired;
}
+void
+ACE_Timer_Queue::upcall (ACE_Event_Handler *handler,
+ const void *arg,
+ const ACE_Time_Value &cur_time)
+{
+ if (this->upcall_strategy_ == 0)
+ {
+ // Perform the callback.
+ if (handler->handle_timeout (cur_time, arg) == -1)
+ this->cancel (handler, 0); // 0 means "call handle_close()".
+ }
+ else
+ // Pass the information along to the strategy
+ this->upcall_strategy_->upcall (handler, arg, cur_time);
+}
+
+
ACE_Time_Value
ACE_Timer_Queue::gettimeofday (void)
{
@@ -187,3 +204,13 @@ ACE_Timer_Queue::gettimeofday (ACE_Time_Value (*gettimeofday)(void))
gettimeofday_ = gettimeofday;
}
+#if defined (ACE_MT_SAFE)
+
+ACE_Recursive_Thread_Mutex &
+ACE_Timer_Queue::lock (void)
+{
+ return this->lock_;
+}
+
+#endif /* ACE_MT_SAFE */
+
diff --git a/ace/Timer_Queue.h b/ace/Timer_Queue.h
index cdf0ee9ef9d..6c5fa062020 100644
--- a/ace/Timer_Queue.h
+++ b/ace/Timer_Queue.h
@@ -97,6 +97,9 @@ public:
// seen, else 1.
};
+// Forward declaration.
+class ACE_Upcall_Strategy;
+
class ACE_Export ACE_Timer_Queue
// = TITLE
// Provides an interface to timers.
@@ -108,8 +111,10 @@ class ACE_Export ACE_Timer_Queue
{
public:
// = Initialization and termination methods.
- ACE_Timer_Queue (void);
- // Default constructor.
+ ACE_Timer_Queue (ACE_Upcall_Strategy *upcall_strategy = 0);
+ // Default constructor. <expire> will call <upcall_strategy->upcall>
+ // if <upcall_strategy> is not 0. Else it will call <handle_timeout>
+ // on the <Event_Handler>
virtual ~ACE_Timer_Queue (void);
// Destructor - make virtual for proper destruction of inherited
@@ -187,6 +192,11 @@ public:
void timer_skew (const ACE_Time_Value &skew);
const ACE_Time_Value &timer_skew (void) const;
+#if defined (ACE_MT_SAFE)
+ ACE_Recursive_Thread_Mutex &lock (void);
+ // Synchronization variable used by the queue
+#endif /* ACE_MT_SAFE */
+
virtual void dump (void) const;
// Dump the state of an object.
@@ -194,6 +204,13 @@ public:
// Declare the dynamic allocation hooks.
protected:
+
+ virtual void upcall (ACE_Event_Handler *handler,
+ const void *arg,
+ const ACE_Time_Value &cur_time);
+ // This method will call <handle_timeout> on the <handler> or will
+ // forward the parameters to an upcall strategy (if one is present)
+
virtual void reschedule (ACE_Timer_Node *) = 0;
// Reschedule an "interval" <ACE_Timer_Node>.
@@ -214,6 +231,9 @@ protected:
ACE_Time_Value (*gettimeofday_)(void);
// Pointer to function that returns the current time of day.
+ ACE_Upcall_Strategy *upcall_strategy_;
+ // Upcall Strategy for callbacks
+
private:
ACE_Time_Value timeout_;
// Returned by <calculate_timeout>.
diff --git a/examples/Reactor/Proactor/test_proactor.mak b/examples/Reactor/Proactor/test_proactor.mak
index 2579cccae78..ee0650f7bdb 100644
--- a/examples/Reactor/Proactor/test_proactor.mak
+++ b/examples/Reactor/Proactor/test_proactor.mak
@@ -4,25 +4,24 @@
# TARGTYPE "Win32 (x86) Console Application" 0x0103
!IF "$(CFG)" == ""
-CFG=test_proactor - Win32 Debug
-!MESSAGE No configuration specified. Defaulting to test_proactor - Win32\
- Debug.
+CFG=test_timeout - Win32 Debug
+!MESSAGE No configuration specified. Defaulting to test_timeout - Win32 Debug.
!ENDIF
-!IF "$(CFG)" != "test_proactor - Win32 Release" && "$(CFG)" !=\
- "test_proactor - Win32 Debug"
+!IF "$(CFG)" != "test_proactor - Win32 Debug" && "$(CFG)" !=\
+ "test_timeout - Win32 Debug"
!MESSAGE Invalid configuration "$(CFG)" specified.
!MESSAGE You can specify a configuration when running NMAKE on this makefile
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE
-!MESSAGE NMAKE /f "test_proactor.mak" CFG="test_proactor - Win32 Debug"
+!MESSAGE NMAKE /f "test_proactor.mak" CFG="test_timeout - Win32 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
-!MESSAGE "test_proactor - Win32 Release" (based on\
- "Win32 (x86) Console Application")
!MESSAGE "test_proactor - Win32 Debug" (based on\
"Win32 (x86) Console Application")
+!MESSAGE "test_timeout - Win32 Debug" (based on\
+ "Win32 (x86) Console Application")
!MESSAGE
!ERROR An invalid configuration is specified.
!ENDIF
@@ -34,30 +33,45 @@ NULL=nul
!ENDIF
################################################################################
# Begin Project
+# PROP Target_Last_Scanned "test_proactor - Win32 Debug"
RSC=rc.exe
CPP=cl.exe
-!IF "$(CFG)" == "test_proactor - Win32 Release"
+!IF "$(CFG)" == "test_proactor - Win32 Debug"
# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Use_Debug_Libraries 1
# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-OUTDIR=.
-INTDIR=.
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "."
+# PROP Intermediate_Dir "debug"
+OUTDIR=.\.
+INTDIR=.\debug
ALL : "$(OUTDIR)\test_proactor.exe"
CLEAN :
-@erase "$(INTDIR)\test_proactor.obj"
+ -@erase "$(INTDIR)\vc40.idb"
+ -@erase "$(INTDIR)\vc40.pdb"
-@erase "$(OUTDIR)\test_proactor.exe"
+ -@erase "$(OUTDIR)\test_proactor.ilk"
+ -@erase "$(OUTDIR)\test_proactor.pdb"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+"$(INTDIR)" :
+ if not exist "$(INTDIR)/$(NULL)" mkdir "$(INTDIR)"
-# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /YX /c
-# ADD CPP /nologo /MDd /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /YX /c
-CPP_PROJ=/nologo /MDd /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE"\
- /Fp"test_proactor.pch" /YX /c
-# ADD BASE RSC /l 0x409 /d "NDEBUG"
-# ADD RSC /l 0x409 /d "NDEBUG"
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /YX /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /YX /c
+CPP_PROJ=/nologo /MDd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE"\
+ /Fp"$(INTDIR)/test_proactor.pch" /YX /Fo"$(INTDIR)/" /Fd"$(INTDIR)/" /c
+CPP_OBJS=.\debug/
+CPP_SBRS=.\.
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
@@ -65,12 +79,12 @@ BSC32_FLAGS=/nologo /o"$(OUTDIR)/test_proactor.bsc"
BSC32_SBRS= \
LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
-# ADD LINK32 ace.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386
+# ADD LINK32 ace.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386
LINK32_FLAGS=ace.lib kernel32.lib user32.lib gdi32.lib winspool.lib\
comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib\
- odbc32.lib odbccp32.lib /nologo /subsystem:console /incremental:no\
- /pdb:"$(OUTDIR)/test_proactor.pdb" /machine:I386\
+ odbc32.lib odbccp32.lib /nologo /subsystem:console /incremental:yes\
+ /pdb:"$(OUTDIR)/test_proactor.pdb" /debug /machine:I386\
/out:"$(OUTDIR)/test_proactor.exe"
LINK32_OBJS= \
"$(INTDIR)\test_proactor.obj"
@@ -80,35 +94,49 @@ LINK32_OBJS= \
$(LINK32_FLAGS) $(LINK32_OBJS)
<<
-!ELSEIF "$(CFG)" == "test_proactor - Win32 Debug"
+!ELSEIF "$(CFG)" == "test_timeout - Win32 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "test_timeout\Debug"
+# PROP BASE Intermediate_Dir "test_timeout\Debug"
+# PROP BASE Target_Dir "test_timeout"
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
-OUTDIR=.
-INTDIR=.
+# PROP Output_Dir "."
+# PROP Intermediate_Dir "Debug"
+# PROP Target_Dir "test_timeout"
+OUTDIR=.\.
+INTDIR=.\Debug
-ALL : "$(OUTDIR)\test_proactor.exe"
+ALL : "$(OUTDIR)\test_timeout.exe"
CLEAN :
- -@erase "$(INTDIR)\test_proactor.obj"
+ -@erase "$(INTDIR)\test_timeout.obj"
-@erase "$(INTDIR)\vc40.idb"
-@erase "$(INTDIR)\vc40.pdb"
- -@erase "$(OUTDIR)\test_proactor.exe"
- -@erase "$(OUTDIR)\test_proactor.ilk"
- -@erase "$(OUTDIR)\test_proactor.pdb"
+ -@erase "$(OUTDIR)\test_timeout.exe"
+ -@erase "$(OUTDIR)\test_timeout.ilk"
+ -@erase "$(OUTDIR)\test_timeout.pdb"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+"$(INTDIR)" :
+ if not exist "$(INTDIR)/$(NULL)" mkdir "$(INTDIR)"
# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /YX /c
# ADD CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /YX /c
CPP_PROJ=/nologo /MDd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE"\
- /Fp"test_proactor.pch" /YX /c
+ /Fp"$(INTDIR)/test_timeout.pch" /YX /Fo"$(INTDIR)/" /Fd"$(INTDIR)/" /c
+CPP_OBJS=.\Debug/
+CPP_SBRS=.\.
# ADD BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
-BSC32_FLAGS=/nologo /o"$(OUTDIR)/test_proactor.bsc"
+BSC32_FLAGS=/nologo /o"$(OUTDIR)/test_timeout.bsc"
BSC32_SBRS= \
LINK32=link.exe
@@ -117,48 +145,40 @@ LINK32=link.exe
LINK32_FLAGS=ace.lib kernel32.lib user32.lib gdi32.lib winspool.lib\
comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib\
odbc32.lib odbccp32.lib /nologo /subsystem:console /incremental:yes\
- /pdb:"$(OUTDIR)/test_proactor.pdb" /debug /machine:I386\
- /out:"$(OUTDIR)/test_proactor.exe"
+ /pdb:"$(OUTDIR)/test_timeout.pdb" /debug /machine:I386\
+ /out:"$(OUTDIR)/test_timeout.exe"
LINK32_OBJS= \
- "$(INTDIR)\test_proactor.obj"
+ "$(INTDIR)\test_timeout.obj"
-"$(OUTDIR)\test_proactor.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+"$(OUTDIR)\test_timeout.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
$(LINK32) @<<
$(LINK32_FLAGS) $(LINK32_OBJS)
<<
!ENDIF
-.c.obj:
+.c{$(CPP_OBJS)}.obj:
$(CPP) $(CPP_PROJ) $<
-.cpp.obj:
+.cpp{$(CPP_OBJS)}.obj:
$(CPP) $(CPP_PROJ) $<
-.cxx.obj:
+.cxx{$(CPP_OBJS)}.obj:
$(CPP) $(CPP_PROJ) $<
-.c.sbr:
+.c{$(CPP_SBRS)}.sbr:
$(CPP) $(CPP_PROJ) $<
-.cpp.sbr:
+.cpp{$(CPP_SBRS)}.sbr:
$(CPP) $(CPP_PROJ) $<
-.cxx.sbr:
+.cxx{$(CPP_SBRS)}.sbr:
$(CPP) $(CPP_PROJ) $<
################################################################################
# Begin Target
-# Name "test_proactor - Win32 Release"
# Name "test_proactor - Win32 Debug"
-
-!IF "$(CFG)" == "test_proactor - Win32 Release"
-
-!ELSEIF "$(CFG)" == "test_proactor - Win32 Debug"
-
-!ENDIF
-
################################################################################
# Begin Source File
@@ -278,5 +298,130 @@ DEP_CPP_TEST_=\
# End Source File
# End Target
+################################################################################
+# Begin Target
+
+# Name "test_timeout - Win32 Debug"
+################################################################################
+# Begin Source File
+
+SOURCE=.\test_timeout.cpp
+DEP_CPP_TEST_T=\
+ {$(INCLUDE)}"\ace\ACE.h"\
+ {$(INCLUDE)}"\ace\ACE.i"\
+ {$(INCLUDE)}"\ace\Addr.h"\
+ {$(INCLUDE)}"\ace\Addr.i"\
+ {$(INCLUDE)}"\ace\Asynch_IO.h"\
+ {$(INCLUDE)}"\ace\Asynch_IO.i"\
+ {$(INCLUDE)}"\ace\config-win32-common.h"\
+ {$(INCLUDE)}"\ace\config.h"\
+ {$(INCLUDE)}"\ace\Event_Handler.h"\
+ {$(INCLUDE)}"\ace\Event_Handler.i"\
+ {$(INCLUDE)}"\ace\Handle_Set.h"\
+ {$(INCLUDE)}"\ace\Handle_Set.i"\
+ {$(INCLUDE)}"\ace\INET_Addr.h"\
+ {$(INCLUDE)}"\ace\INET_Addr.i"\
+ {$(INCLUDE)}"\ace\IO_Cntl_Msg.h"\
+ {$(INCLUDE)}"\ace\IPC_SAP.h"\
+ {$(INCLUDE)}"\ace\IPC_SAP.i"\
+ {$(INCLUDE)}"\ace\Local_Tokens.h"\
+ {$(INCLUDE)}"\ace\Local_Tokens.i"\
+ {$(INCLUDE)}"\ace\Log_Msg.h"\
+ {$(INCLUDE)}"\ace\Log_Priority.h"\
+ {$(INCLUDE)}"\ace\Log_Record.h"\
+ {$(INCLUDE)}"\ace\Log_Record.i"\
+ {$(INCLUDE)}"\ace\Malloc.h"\
+ {$(INCLUDE)}"\ace\Malloc.i"\
+ {$(INCLUDE)}"\ace\Malloc_T.cpp"\
+ {$(INCLUDE)}"\ace\Malloc_T.h"\
+ {$(INCLUDE)}"\ace\Malloc_T.i"\
+ {$(INCLUDE)}"\ace\Map_Manager.cpp"\
+ {$(INCLUDE)}"\ace\Map_Manager.h"\
+ {$(INCLUDE)}"\ace\Map_Manager.i"\
+ {$(INCLUDE)}"\ace\Mem_Map.h"\
+ {$(INCLUDE)}"\ace\Mem_Map.i"\
+ {$(INCLUDE)}"\ace\Memory_Pool.h"\
+ {$(INCLUDE)}"\ace\Memory_Pool.i"\
+ {$(INCLUDE)}"\ace\Message_Block.h"\
+ {$(INCLUDE)}"\ace\Message_Block.i"\
+ {$(INCLUDE)}"\ace\Message_Queue.cpp"\
+ {$(INCLUDE)}"\ace\Message_Queue.h"\
+ {$(INCLUDE)}"\ace\Message_Queue.i"\
+ {$(INCLUDE)}"\ace\Module.cpp"\
+ {$(INCLUDE)}"\ace\Module.h"\
+ {$(INCLUDE)}"\ace\Module.i"\
+ {$(INCLUDE)}"\ace\OS.h"\
+ {$(INCLUDE)}"\ace\OS.i"\
+ {$(INCLUDE)}"\ace\Pipe.h"\
+ {$(INCLUDE)}"\ace\Pipe.i"\
+ {$(INCLUDE)}"\ace\Proactor.h"\
+ {$(INCLUDE)}"\ace\Proactor.i"\
+ {$(INCLUDE)}"\ace\Reactor.h"\
+ {$(INCLUDE)}"\ace\Reactor.i"\
+ {$(INCLUDE)}"\ace\ReactorEx.h"\
+ {$(INCLUDE)}"\ace\ReactorEx.i"\
+ {$(INCLUDE)}"\ace\Service_Config.h"\
+ {$(INCLUDE)}"\ace\Service_Config.i"\
+ {$(INCLUDE)}"\ace\Service_Object.h"\
+ {$(INCLUDE)}"\ace\Service_Object.i"\
+ {$(INCLUDE)}"\ace\Set.cpp"\
+ {$(INCLUDE)}"\ace\Set.h"\
+ {$(INCLUDE)}"\ace\Set.i"\
+ {$(INCLUDE)}"\ace\Shared_Object.h"\
+ {$(INCLUDE)}"\ace\Shared_Object.i"\
+ {$(INCLUDE)}"\ace\Signal.h"\
+ {$(INCLUDE)}"\ace\Signal.i"\
+ {$(INCLUDE)}"\ace\SOCK.h"\
+ {$(INCLUDE)}"\ace\SOCK.i"\
+ {$(INCLUDE)}"\ace\SOCK_IO.h"\
+ {$(INCLUDE)}"\ace\SOCK_IO.i"\
+ {$(INCLUDE)}"\ace\SOCK_Stream.h"\
+ {$(INCLUDE)}"\ace\SOCK_Stream.i"\
+ {$(INCLUDE)}"\ace\SString.h"\
+ {$(INCLUDE)}"\ace\SString.i"\
+ {$(INCLUDE)}"\ace\Stack.cpp"\
+ {$(INCLUDE)}"\ace\Stack.h"\
+ {$(INCLUDE)}"\ace\Stack.i"\
+ {$(INCLUDE)}"\ace\stdcpp.h"\
+ {$(INCLUDE)}"\ace\Strategies.h"\
+ {$(INCLUDE)}"\ace\Strategies_T.cpp"\
+ {$(INCLUDE)}"\ace\Strategies_T.h"\
+ {$(INCLUDE)}"\ace\Stream_Modules.cpp"\
+ {$(INCLUDE)}"\ace\Stream_Modules.h"\
+ {$(INCLUDE)}"\ace\Stream_Modules.i"\
+ {$(INCLUDE)}"\ace\SV_Semaphore_Complex.h"\
+ {$(INCLUDE)}"\ace\SV_Semaphore_Complex.i"\
+ {$(INCLUDE)}"\ace\SV_Semaphore_Simple.h"\
+ {$(INCLUDE)}"\ace\SV_Semaphore_Simple.i"\
+ {$(INCLUDE)}"\ace\Svc_Conf_Tokens.h"\
+ {$(INCLUDE)}"\ace\Synch.h"\
+ {$(INCLUDE)}"\ace\Synch.i"\
+ {$(INCLUDE)}"\ace\Synch_Options.h"\
+ {$(INCLUDE)}"\ace\Synch_T.cpp"\
+ {$(INCLUDE)}"\ace\Synch_T.h"\
+ {$(INCLUDE)}"\ace\Synch_T.i"\
+ {$(INCLUDE)}"\ace\Task.h"\
+ {$(INCLUDE)}"\ace\Task.i"\
+ {$(INCLUDE)}"\ace\Task_T.cpp"\
+ {$(INCLUDE)}"\ace\Task_T.h"\
+ {$(INCLUDE)}"\ace\Task_T.i"\
+ {$(INCLUDE)}"\ace\Thread.h"\
+ {$(INCLUDE)}"\ace\Thread.i"\
+ {$(INCLUDE)}"\ace\Thread_Manager.h"\
+ {$(INCLUDE)}"\ace\Thread_Manager.i"\
+ {$(INCLUDE)}"\ace\Time_Value.h"\
+ {$(INCLUDE)}"\ace\Timer_Queue.h"\
+ {$(INCLUDE)}"\ace\Timer_Queue.i"\
+ {$(INCLUDE)}"\ace\Token.h"\
+ {$(INCLUDE)}"\ace\Token.i"\
+ {$(INCLUDE)}"\ace\Trace.h"\
+ {$(INCLUDE)}"\ace\ws2tcpip.h"\
+
+
+"$(INTDIR)\test_timeout.obj" : $(SOURCE) $(DEP_CPP_TEST_T) "$(INTDIR)"
+
+
+# End Source File
+# End Target
# End Project
################################################################################
diff --git a/examples/Reactor/Proactor/test_proactor.mdp b/examples/Reactor/Proactor/test_proactor.mdp
index d03e368531f..14d0497de94 100644
--- a/examples/Reactor/Proactor/test_proactor.mdp
+++ b/examples/Reactor/Proactor/test_proactor.mdp
Binary files differ
diff --git a/examples/Reactor/Proactor/test_timeout.cpp b/examples/Reactor/Proactor/test_timeout.cpp
new file mode 100644
index 00000000000..55a36ccc93d
--- /dev/null
+++ b/examples/Reactor/Proactor/test_timeout.cpp
@@ -0,0 +1,92 @@
+// $Id: test_timeout.cpp
+
+// ============================================================================
+//
+// = LIBRARY
+// examples
+//
+// = FILENAME
+// test_timeout.cpp
+//
+// = DESCRIPTION
+//
+// This example application shows how to write event loops that
+// handle events for some fixed amount of time. Note that any
+// thread in the Proactor thread pool can call back the handler
+//
+// = AUTHOR
+// Irfan Pyarali
+//
+// ============================================================================
+
+#include "ace/Proactor.h"
+#include "ace/Synch.h"
+#include "ace/Task.h"
+
+class Timeout_Handler : public ACE_Handler
+// = TITLE
+// Generic timeout handler.
+{
+public:
+ Timeout_Handler (void)
+ {
+ }
+
+ virtual void handle_timeout (const ACE_Time_Value &tv,
+ const void *arg)
+ // Print out when timeouts occur.
+ {
+ ACE_DEBUG ((LM_DEBUG, "(%t) %d timeout occurred for %s @ %d.\n",
+ ++count_,
+ (char *) arg,
+ tv.sec ()));
+ // Sleep for a while
+ ACE_OS::sleep (4);
+ }
+
+private:
+ ACE_Atomic_Op <ACE_Thread_Mutex, int> count_;
+};
+
+class Worker : public ACE_Task <ACE_NULL_SYNCH>
+{
+public:
+ int svc (void)
+ {
+ // Handle events for 13 seconds.
+ ACE_Time_Value run_time (13);
+
+ if (ACE_Service_Config::run_proactor_event_loop (run_time) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, "%p.\n", "Worker::svc"), -1);
+ else
+ ACE_DEBUG ((LM_DEBUG, "(%t) work complete\n"));
+
+ return 0;
+ }
+};
+
+int
+main ()
+{
+ Timeout_Handler handler;
+
+ // Register a 2 second timer.
+ ACE_Time_Value foo_tv (2);
+ ACE_Service_Config::proactor ()->schedule_timer (handler,
+ (void *) "Foo",
+ ACE_Time_Value::zero,
+ foo_tv);
+ // Register a 3 second timer.
+ ACE_Time_Value bar_tv (3);
+ ACE_Service_Config::proactor ()->schedule_timer (handler,
+ (void *) "Bar",
+ ACE_Time_Value::zero,
+ bar_tv);
+
+ Worker worker;
+ if (worker.activate (THR_NEW_LWP, 10) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, "%p.\n", "main"), -1);
+
+ ACE_Service_Config::thr_mgr ()->wait ();
+ return 0;
+}