LCOV - code coverage report
Current view: directory - ipc/chromium/src/base - timer.h (source / functions) Found Hit Coverage
Test: app.info Lines: 48 0 0.0 %
Date: 2012-06-02 Functions: 52 0 0.0 %

       1                 : // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
       2                 : // Use of this source code is governed by a BSD-style license that can be
       3                 : // found in the LICENSE file.
       4                 : 
       5                 : // OneShotTimer and RepeatingTimer provide a simple timer API.  As the names
       6                 : // suggest, OneShotTimer calls you back once after a time delay expires.
       7                 : // RepeatingTimer on the other hand calls you back periodically with the
       8                 : // prescribed time interval.
       9                 : //
      10                 : // OneShotTimer and RepeatingTimer both cancel the timer when they go out of
      11                 : // scope, which makes it easy to ensure that you do not get called when your
      12                 : // object has gone out of scope.  Just instantiate a OneShotTimer or
      13                 : // RepeatingTimer as a member variable of the class for which you wish to
      14                 : // receive timer events.
      15                 : //
      16                 : // Sample RepeatingTimer usage:
      17                 : //
      18                 : //   class MyClass {
      19                 : //    public:
      20                 : //     void StartDoingStuff() {
      21                 : //       timer_.Start(TimeDelta::FromSeconds(1), this, &MyClass::DoStuff);
      22                 : //     }
      23                 : //     void StopDoingStuff() {
      24                 : //       timer_.Stop();
      25                 : //     }
      26                 : //    private:
      27                 : //     void DoStuff() {
      28                 : //       // This method is called every second to do stuff.
      29                 : //       ...
      30                 : //     }
      31                 : //     base::RepeatingTimer<MyClass> timer_;
      32                 : //   };
      33                 : //
      34                 : // Both OneShotTimer and RepeatingTimer also support a Reset method, which
      35                 : // allows you to easily defer the timer event until the timer delay passes once
      36                 : // again.  So, in the above example, if 0.5 seconds have already passed,
      37                 : // calling Reset on timer_ would postpone DoStuff by another 1 second.  In
      38                 : // other words, Reset is shorthand for calling Stop and then Start again with
      39                 : // the same arguments.
      40                 : 
      41                 : #ifndef BASE_TIMER_H_
      42                 : #define BASE_TIMER_H_
      43                 : 
      44                 : // IMPORTANT: If you change timer code, make sure that all tests (including
      45                 : // disabled ones) from timer_unittests.cc pass locally. Some are disabled
      46                 : // because they're flaky on the buildbot, but when you run them locally you
      47                 : // should be able to tell the difference.
      48                 : 
      49                 : #include "base/logging.h"
      50                 : #include "base/task.h"
      51                 : #include "base/time.h"
      52                 : 
      53                 : class MessageLoop;
      54                 : 
      55                 : namespace base {
      56                 : 
      57                 : //-----------------------------------------------------------------------------
      58                 : // This class is an implementation detail of OneShotTimer and RepeatingTimer.
      59                 : // Please do not use this class directly.
      60                 : //
      61                 : // This class exists to share code between BaseTimer<T> template instantiations.
      62                 : //
      63                 : class BaseTimer_Helper {
      64                 :  public:
      65                 :   // Stops the timer.
      66               0 :   ~BaseTimer_Helper() {
      67               0 :     OrphanDelayedTask();
      68               0 :   }
      69                 : 
      70                 :   // Returns true if the timer is running (i.e., not stopped).
      71               0 :   bool IsRunning() const {
      72               0 :     return delayed_task_ != NULL;
      73                 :   }
      74                 : 
      75                 :   // Returns the current delay for this timer.  May only call this method when
      76                 :   // the timer is running!
      77                 :   TimeDelta GetCurrentDelay() const {
      78                 :     DCHECK(IsRunning());
      79                 :     return delayed_task_->delay_;
      80                 :   }
      81                 : 
      82                 :  protected:
      83               0 :   BaseTimer_Helper() : delayed_task_(NULL) {}
      84                 : 
      85                 :   // We have access to the timer_ member so we can orphan this task.
      86                 :   class TimerTask : public Task {
      87                 :    public:
      88               0 :     TimerTask(TimeDelta delay) : delay_(delay) {
      89                 :       // timer_ is set in InitiateDelayedTask.
      90               0 :     }
      91               0 :     virtual ~TimerTask() {}
      92                 :     BaseTimer_Helper* timer_;
      93                 :     TimeDelta delay_;
      94                 :   };
      95                 : 
      96                 :   // Used to orphan delayed_task_ so that when it runs it does nothing.
      97                 :   void OrphanDelayedTask();
      98                 : 
      99                 :   // Used to initiated a new delayed task.  This has the side-effect of
     100                 :   // orphaning delayed_task_ if it is non-null.
     101                 :   void InitiateDelayedTask(TimerTask* timer_task);
     102                 : 
     103                 :   TimerTask* delayed_task_;
     104                 : 
     105                 :   DISALLOW_COPY_AND_ASSIGN(BaseTimer_Helper);
     106                 : };
     107                 : 
     108                 : //-----------------------------------------------------------------------------
     109                 : // This class is an implementation detail of OneShotTimer and RepeatingTimer.
     110                 : // Please do not use this class directly.
     111                 : template <class Receiver, bool kIsRepeating>
     112               0 : class BaseTimer : public BaseTimer_Helper {
     113                 :  public:
     114                 :   typedef void (Receiver::*ReceiverMethod)();
     115                 : 
     116                 :   // Call this method to start the timer.  It is an error to call this method
     117                 :   // while the timer is already running.
     118               0 :   void Start(TimeDelta delay, Receiver* receiver, ReceiverMethod method) {
     119               0 :     DCHECK(!IsRunning());
     120               0 :     InitiateDelayedTask(new TimerTask(delay, receiver, method));
     121               0 :   }
     122                 : 
     123                 :   // Call this method to stop the timer.  It is a no-op if the timer is not
     124                 :   // running.
     125               0 :   void Stop() {
     126               0 :     OrphanDelayedTask();
     127               0 :   }
     128                 : 
     129                 :   // Call this method to reset the timer delay of an already running timer.
     130               0 :   void Reset() {
     131               0 :     DCHECK(IsRunning());
     132               0 :     InitiateDelayedTask(static_cast<TimerTask*>(delayed_task_)->Clone());
     133               0 :   }
     134                 : 
     135                 :  private:
     136                 :   typedef BaseTimer<Receiver, kIsRepeating> SelfType;
     137                 : 
     138                 :   class TimerTask : public BaseTimer_Helper::TimerTask {
     139                 :    public:
     140               0 :     TimerTask(TimeDelta delay, Receiver* receiver, ReceiverMethod method)
     141                 :         : BaseTimer_Helper::TimerTask(delay),
     142                 :           receiver_(receiver),
     143               0 :           method_(method) {
     144               0 :     }
     145                 : 
     146               0 :     virtual ~TimerTask() {
     147                 :       // This task may be getting cleared because the MessageLoop has been
     148                 :       // destructed.  If so, don't leave the Timer with a dangling pointer
     149                 :       // to this now-defunct task.
     150               0 :       ClearBaseTimer();
     151               0 :     }
     152                 : 
     153               0 :     virtual void Run() {
     154               0 :       if (!timer_)  // timer_ is null if we were orphaned.
     155               0 :         return;
     156                 :       if (kIsRepeating)
     157               0 :         ResetBaseTimer();
     158                 :       else
     159                 :         ClearBaseTimer();
     160               0 :       DispatchToMethod(receiver_, method_, Tuple0());
     161                 :     }
     162                 : 
     163               0 :     TimerTask* Clone() const {
     164               0 :       return new TimerTask(delay_, receiver_, method_);
     165                 :     }
     166                 : 
     167                 :    private:
     168                 :     // Inform the Base that the timer is no longer active.
     169               0 :     void ClearBaseTimer() {
     170               0 :       if (timer_) {
     171               0 :         SelfType* self = static_cast<SelfType*>(timer_);
     172                 :         // It is possible that the Timer has already been reset, and that this
     173                 :         // Task is old.  So, if the Timer points to a different task, assume
     174                 :         // that the Timer has already taken care of properly setting the task.
     175               0 :         if (self->delayed_task_ == this)
     176               0 :           self->delayed_task_ = NULL;
     177                 :         // By now the delayed_task_ in the Timer does not point to us anymore.
     178                 :         // We should reset our own timer_ because the Timer can not do this
     179                 :         // for us in its destructor.
     180               0 :         timer_ = NULL;
     181                 :       }
     182               0 :     }
     183                 : 
     184                 :     // Inform the Base that we're resetting the timer.
     185               0 :     void ResetBaseTimer() {
     186               0 :       DCHECK(timer_);
     187                 :       DCHECK(kIsRepeating);
     188               0 :       SelfType* self = static_cast<SelfType*>(timer_);
     189               0 :       self->Reset();
     190               0 :     }
     191                 : 
     192                 :     Receiver* receiver_;
     193                 :     ReceiverMethod method_;
     194                 :   };
     195                 : };
     196                 : 
     197                 : //-----------------------------------------------------------------------------
     198                 : // A simple, one-shot timer.  See usage notes at the top of the file.
     199                 : template <class Receiver>
     200               0 : class OneShotTimer : public BaseTimer<Receiver, false> {};
     201                 : 
     202                 : //-----------------------------------------------------------------------------
     203                 : // A simple, repeating timer.  See usage notes at the top of the file.
     204                 : template <class Receiver>
     205               0 : class RepeatingTimer : public BaseTimer<Receiver, true> {};
     206                 : 
     207                 : //-----------------------------------------------------------------------------
     208                 : // A Delay timer is like The Button from Lost. Once started, you have to keep
     209                 : // calling Reset otherwise it will call the given method in the MessageLoop
     210                 : // thread.
     211                 : //
     212                 : // Once created, it is inactive until Reset is called. Once |delay| seconds have
     213                 : // passed since the last call to Reset, the callback is made. Once the callback
     214                 : // has been made, it's inactive until Reset is called again.
     215                 : //
     216                 : // If destroyed, the timeout is canceled and will not occur even if already
     217                 : // inflight.
     218                 : template <class Receiver>
     219                 : class DelayTimer {
     220                 :  public:
     221                 :   typedef void (Receiver::*ReceiverMethod)();
     222                 : 
     223                 :   DelayTimer(TimeDelta delay, Receiver* receiver, ReceiverMethod method)
     224                 :       : receiver_(receiver),
     225                 :         method_(method),
     226                 :         delay_(delay) {
     227                 :   }
     228                 : 
     229                 :   void Reset() {
     230                 :     DelayFor(delay_);
     231                 :   }
     232                 : 
     233                 :  private:
     234                 :   void DelayFor(TimeDelta delay) {
     235                 :     trigger_time_ = Time::Now() + delay;
     236                 : 
     237                 :     // If we already have a timer that will expire at or before the given delay,
     238                 :     // then we have nothing more to do now.
     239                 :     if (timer_.IsRunning() && timer_.GetCurrentDelay() <= delay)
     240                 :       return;
     241                 : 
     242                 :     // The timer isn't running, or will expire too late, so restart it.
     243                 :     timer_.Stop();
     244                 :     timer_.Start(delay, this, &DelayTimer<Receiver>::Check);
     245                 :   }
     246                 : 
     247                 :   void Check() {
     248                 :     if (trigger_time_.is_null())
     249                 :       return;
     250                 : 
     251                 :     // If we have not waited long enough, then wait some more.
     252                 :     const Time now = Time::Now();
     253                 :     if (now < trigger_time_) {
     254                 :       DelayFor(trigger_time_ - now);
     255                 :       return;
     256                 :     }
     257                 : 
     258                 :     (receiver_->*method_)();
     259                 :   }
     260                 : 
     261                 :   Receiver *const receiver_;
     262                 :   const ReceiverMethod method_;
     263                 :   const TimeDelta delay_;
     264                 : 
     265                 :   OneShotTimer<DelayTimer<Receiver> > timer_;
     266                 :   Time trigger_time_;
     267                 : };
     268                 : 
     269                 : }  // namespace base
     270                 : 
     271                 : #endif  // BASE_TIMER_H_

Generated by: LCOV version 1.7