Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members   Related Pages  

Timer_Queue_Adapters.cpp

Go to the documentation of this file.
00001 // $Id: Timer_Queue_Adapters.cpp,v 1.1.1.4 2003/02/21 18:36:32 chad Exp $
00002 
00003 #include "ace/Timer_Queue_Adapters.h"
00004 
00005 #if !defined (ACE_LACKS_PRAGMA_ONCE)
00006 # pragma once
00007 #endif /* ACE_LACKS_PRAGMA_ONCE */
00008 
00009 #ifndef ACE_TIMER_QUEUE_ADAPTERS_C
00010 # define ACE_TIMER_QUEUE_ADAPTERS_C
00011 
00012 ACE_RCSID(ace, Timer_Queue_Adapters, "$Id: Timer_Queue_Adapters.cpp,v 1.1.1.4 2003/02/21 18:36:32 chad Exp $")
00013 
00014 # if !defined (__ACE_INLINE__)
00015 #  include "ace/Timer_Queue_Adapters.i"
00016 # endif /* __ACE_INLINE__ */
00017 
00018 template <class TQ> TQ &
00019 ACE_Async_Timer_Queue_Adapter<TQ>::timer_queue (void)
00020 {
00021   return this->timer_queue_;
00022 }
00023 
00024 template <class TQ> int
00025 ACE_Async_Timer_Queue_Adapter<TQ>::cancel (long timer_id,
00026                                            const void **act)
00027 {
00028   // Block designated signals.
00029   ACE_Sig_Guard sg (&this->mask_);
00030   ACE_UNUSED_ARG (sg);
00031 
00032   return this->timer_queue_.cancel (timer_id, act);
00033 }
00034 
00035 template <class TQ> int
00036 ACE_Async_Timer_Queue_Adapter<TQ>::expire (void)
00037 {
00038   // Block designated signals.
00039   ACE_Sig_Guard sg (&this->mask_);
00040   ACE_UNUSED_ARG (sg);
00041 
00042   return this->timer_queue_.expire ();
00043 }
00044 
00045 template <class TQ> int
00046 ACE_Async_Timer_Queue_Adapter<TQ>::schedule_ualarm (void)
00047 {
00048   ACE_Time_Value tv = this->timer_queue_.earliest_time ()
00049     - ACE_OS::gettimeofday ();
00050 
00051   // Beware of negative times and zero times (which cause problems for
00052   // <ualarm>).
00053   if (tv < ACE_Time_Value::zero)
00054     tv = ACE_Time_Value (0, 1);
00055 
00056   // @@ This code should be clever enough to avoid updating the
00057   // <ualarm> if we haven't actually changed the earliest time.
00058   // Schedule a new timer.
00059   ACE_OS::ualarm (tv);
00060   return 0;
00061 }
00062 
00063 template <class TQ> long
00064 ACE_Async_Timer_Queue_Adapter<TQ>::schedule (ACE_Event_Handler *eh,
00065                                              const void *act,
00066                                              const ACE_Time_Value &future_time,
00067                                              const ACE_Time_Value &interval)
00068 {
00069   ACE_UNUSED_ARG (act);
00070   ACE_UNUSED_ARG (interval);
00071 
00072   // Block designated signals.
00073   ACE_Sig_Guard sg (&this->mask_);
00074   ACE_UNUSED_ARG (sg);
00075 
00076   // @@ We still need to implement interval timers...
00077   long tid = this->timer_queue_.schedule (eh, act, future_time);
00078 
00079   if (tid == -1)
00080     ACE_ERROR_RETURN ((LM_ERROR,
00081                        ACE_LIB_TEXT ("%p\n"),
00082                        ACE_LIB_TEXT ("schedule_timer")),
00083                       -1);
00084 
00085   if (this->schedule_ualarm () == -1)
00086     return 0;
00087 
00088   return tid;
00089 }
00090 
00091 template <class TQ>
00092 ACE_Async_Timer_Queue_Adapter<TQ>::ACE_Async_Timer_Queue_Adapter (ACE_Sig_Set *mask)
00093   // If <mask> == 0, block *all* signals when the SIGARLM handler is
00094   // running, else just block those in the mask.
00095   : mask_ (mask)
00096 {
00097   // The following code is necessary to selectively "block" certain
00098   // signals when SIGALRM is running.  Also, we always restart system
00099   // calls that are interrupted by the signals.
00100 
00101   ACE_Sig_Action sa ((ACE_SignalHandler) 0,
00102                      this->mask_,
00103                      SA_RESTART);
00104 
00105   if (this->sig_handler_.register_handler (SIGALRM, this, &sa) == -1)
00106     ACE_ERROR ((LM_ERROR,
00107                 ACE_LIB_TEXT ("%p\n"),
00108                 ACE_LIB_TEXT ("register_handler")));
00109 }
00110 
00111 // This is the signal handler function for the asynchronous timer
00112 // list.  It gets invoked asynchronously when the SIGALRM signal
00113 // occurs.
00114 
00115 template <class TQ> int
00116 ACE_Async_Timer_Queue_Adapter<TQ>::handle_signal (int signum,
00117                                                   siginfo_t *,
00118                                                   ucontext_t *)
00119 {
00120   switch (signum)
00121     {
00122     case SIGALRM:
00123       {
00124         // Expire the pending timers.
00125 
00126         // @@ We need to figure out how to implement interval
00127         // timers...
00128         this->timer_queue_.expire ();
00129 
00130         // Only schedule a new timer if there is one in the list.
00131 
00132         // @@ This code should also become smarter to avoid
00133         // unnecessary calls to ualarm().
00134         if (this->timer_queue_.is_empty () == 0)
00135           return this->schedule_ualarm ();
00136         else
00137           return 0;
00138         /* NOTREACHED */
00139       }
00140     default:
00141       ACE_ERROR_RETURN ((LM_ERROR,
00142                          "unexpected signal %S\n",
00143                          signum),
00144                         -1);
00145       /* NOTREACHED */
00146     }
00147 }
00148 
00149 template<class TQ>
00150 ACE_Thread_Timer_Queue_Adapter<TQ>::ACE_Thread_Timer_Queue_Adapter (ACE_Thread_Manager *tm,
00151                                                                     TQ* timer_queue)
00152   : ACE_Task_Base (tm),
00153     timer_queue_(timer_queue),
00154     delete_timer_queue_(0),
00155     condition_ (mutex_),
00156     active_ (1), // Assume that we start in active mode.
00157     thr_id_ (ACE_OS::NULL_thread)
00158 {
00159   if (timer_queue_ == 0)
00160     {
00161       ACE_NEW (this->timer_queue_,
00162                TQ);
00163       this->delete_timer_queue_ = 1;
00164     }
00165 }
00166 
00167 template<class TQ>
00168 ACE_Thread_Timer_Queue_Adapter<TQ>::~ACE_Thread_Timer_Queue_Adapter (void)
00169 {
00170   if (this->delete_timer_queue_)
00171     {
00172       delete this->timer_queue_;
00173       this->timer_queue_ = 0;
00174       this->delete_timer_queue_ = 0;
00175     }
00176 }
00177 
00178 template<class TQ> ACE_SYNCH_RECURSIVE_MUTEX &
00179 ACE_Thread_Timer_Queue_Adapter<TQ>::mutex (void)
00180 {
00181   return this->mutex_;
00182 }
00183 
00184 template<class TQ> long
00185 ACE_Thread_Timer_Queue_Adapter<TQ>::schedule
00186     (ACE_Event_Handler* handler,
00187      const void *act,
00188      const ACE_Time_Value &future_time,
00189      const ACE_Time_Value &interval)
00190 {
00191   ACE_GUARD_RETURN (ACE_SYNCH_RECURSIVE_MUTEX, guard, this->mutex_, -1);
00192 
00193   long result = this->timer_queue_->schedule (handler, act, future_time, interval);
00194   this->condition_.signal ();
00195   return result;
00196 }
00197 
00198 template<class TQ> int
00199 ACE_Thread_Timer_Queue_Adapter<TQ>::cancel (long timer_id,
00200                                             const void **act)
00201 {
00202   ACE_GUARD_RETURN (ACE_SYNCH_RECURSIVE_MUTEX, guard, this->mutex_, -1);
00203 
00204   int result = this->timer_queue_->cancel (timer_id, act);
00205   condition_.signal ();
00206   return result;
00207 }
00208 
00209 template<class TQ> void
00210 ACE_Thread_Timer_Queue_Adapter<TQ>::deactivate (void)
00211 {
00212   ACE_GUARD (ACE_SYNCH_RECURSIVE_MUTEX, guard, this->mutex_);
00213 
00214   this->active_ = 0;
00215   this->condition_.signal ();
00216 }
00217 
00218 template<class TQ> int
00219 ACE_Thread_Timer_Queue_Adapter<TQ>::svc (void)
00220 {
00221   ACE_GUARD_RETURN (ACE_SYNCH_RECURSIVE_MUTEX, guard, this->mutex_, -1);
00222 
00223   this->thr_id_ = ACE_Thread::self ();
00224 
00225   // Thread cancellation point, if ACE supports it.
00226   //
00227   // Note: This call generates a warning under Solaris because the header
00228   //       file /usr/include/pthread.h redefines the routine argument. This
00229   //       is a bug in the Solaris header files and has nothing to do with
00230   //       ACE.
00231 # if !defined (ACE_LACKS_PTHREAD_CANCEL)
00232   ACE_PTHREAD_CLEANUP_PUSH (&this->condition_.mutex ().get_nesting_mutex ());
00233 # endif /* ACE_LACKS_PTHREAD_CANCEL */
00234 
00235   while (this->active_)
00236     {
00237 # if defined (ACE_HAS_DEFERRED_TIMER_COMMANDS)
00238       // Temporarily suspend ownership of the timer queue mutex in
00239       // order to dispatch deferred execution commands.  These
00240       // commands are to be treated as executing in a context
00241       // "external" to the timer queue adapter, and thus must compete
00242       // separately for this lock.
00243       mutex_.release ();
00244       this->dispatch_commands ();
00245 
00246       // Re-acquire ownership of the timer queue mutex in order to
00247       // restore the "internal" timer queue adapter context
00248       mutex_.acquire ();
00249 # endif /* ACE_HAS_DEFERRED_TIMER_COMMANDS */
00250 
00251       // If the queue is empty, sleep until there is a change on it.
00252       if (this->timer_queue_->is_empty ())
00253         this->condition_.wait ();
00254       else
00255         {
00256           // Compute the remaining time, being careful not to sleep
00257           // for "negative" amounts of time.
00258           ACE_Time_Value tv = this->timer_queue_->earliest_time ();
00259 
00260           // ACE_DEBUG ((LM_DEBUG,  ACE_LIB_TEXT ("waiting until %u.%3.3u secs\n"),
00261           // tv.sec(), tv.msec()));
00262           this->condition_.wait (&tv);
00263         }
00264 
00265       // Expire timers anyway, at worst this is a no-op.
00266       this->timer_queue_->expire ();
00267     }
00268 
00269    // Thread cancellation point, if ACE supports it.
00270 # if !defined (ACE_LACKS_PTHREAD_CANCEL)
00271   ACE_PTHREAD_CLEANUP_POP (0);
00272 # endif /* ACE_LACKS_PTHREAD_CANCEL */
00273 
00274   return 0;
00275 }
00276 
00277 # if defined (ACE_HAS_DEFERRED_TIMER_COMMANDS)
00278 
00279 // Enqueues a command object for execution just before waiting on the next
00280 // timer event. This allows deferred execution of commands that cannot
00281 // be performed in the timer event handler context, such as registering
00282 // or cancelling timers on platforms where the timer queue mutex is not
00283 // recursive.
00284 
00285 template<class TQ> int
00286 ACE_Thread_Timer_Queue_Adapter<TQ>::enqueue_command (ACE_Command_Base *cmd,
00287                                                      COMMAND_ENQUEUE_POSITION pos)
00288 {
00289   // Serialize access to the command queue.
00290   ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, guard, this->command_mutex_, -1);
00291 
00292   if (pos == ACE_Thread_Timer_Queue_Adapter<TQ>::TAIL)
00293     return command_queue_.enqueue_tail (cmd);
00294   else
00295     return command_queue_.enqueue_head (cmd);
00296 }
00297 
00298 // Dispatches all command objects enqueued in the most recent event
00299 // handler context.
00300 
00301 template<class TQ> int
00302 ACE_Thread_Timer_Queue_Adapter<TQ>::dispatch_commands (void)
00303 {
00304   // Serialize access to the command queue.
00305   ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, guard, this->command_mutex_, -1);
00306 
00307   // loop through the enqueued commands
00308   ACE_Command_Base *cmd = 0;
00309   while (command_queue_.dequeue_head (cmd) == 0)
00310     if (cmd)
00311       {
00312         cmd->execute ();
00313         delete cmd;
00314       }
00315 
00316   return 0;
00317 }
00318 
00319 # endif /* ACE_HAS_DEFERRED_TIMER_COMMANDS */
00320 
00321 #endif /* ACE_TIMER_QUEUE_ADAPTERS_C*/

Generated on Mon Jun 16 11:21:51 2003 for ACE by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002