Timer_Queue_Adapters.cpp

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

Generated on Thu Nov 9 09:42:07 2006 for ACE by doxygen 1.3.6