Timer_Queue_Adapters.cpp

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

Generated on Tue Feb 2 17:18:43 2010 for ACE by  doxygen 1.4.7