Home | History | Annotate | Download | only in platform
      1 /*
      2  * Copyright (C) 2006 Apple Computer, Inc.  All rights reserved.
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions
      6  * are met:
      7  * 1. Redistributions of source code must retain the above copyright
      8  *    notice, this list of conditions and the following disclaimer.
      9  * 2. Redistributions in binary form must reproduce the above copyright
     10  *    notice, this list of conditions and the following disclaimer in the
     11  *    documentation and/or other materials provided with the distribution.
     12  *
     13  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
     14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
     17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
     20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
     21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     24  */
     25 
     26 #ifndef Timer_h
     27 #define Timer_h
     28 
     29 #include "platform/PlatformExport.h"
     30 #include "platform/TraceLocation.h"
     31 #include "platform/heap/Handle.h"
     32 #include "wtf/Noncopyable.h"
     33 #include "wtf/Threading.h"
     34 #include "wtf/Vector.h"
     35 
     36 namespace WebCore {
     37 
     38 // Time intervals are all in seconds.
     39 
     40 class TimerHeapElement;
     41 
     42 class PLATFORM_EXPORT TimerBase {
     43     WTF_MAKE_NONCOPYABLE(TimerBase); WTF_MAKE_FAST_ALLOCATED_WILL_BE_REMOVED;
     44 public:
     45     TimerBase();
     46     virtual ~TimerBase();
     47 
     48     void start(double nextFireInterval, double repeatInterval, const TraceLocation&);
     49 
     50     void startRepeating(double repeatInterval, const TraceLocation& caller)
     51     {
     52         start(repeatInterval, repeatInterval, caller);
     53     }
     54     void startOneShot(double interval, const TraceLocation& caller)
     55     {
     56         start(interval, 0, caller);
     57     }
     58 
     59     void stop();
     60     bool isActive() const;
     61     const TraceLocation& location() const { return m_location; }
     62 
     63     double nextFireInterval() const;
     64     double nextUnalignedFireInterval() const;
     65     double repeatInterval() const { return m_repeatInterval; }
     66 
     67     void augmentRepeatInterval(double delta) {
     68         setNextFireTime(m_nextFireTime + delta);
     69         m_repeatInterval += delta;
     70     }
     71 
     72     void didChangeAlignmentInterval();
     73 
     74     static void fireTimersInNestedEventLoop();
     75 
     76 private:
     77     virtual void fired() = 0;
     78 
     79     virtual double alignedFireTime(double fireTime) const { return fireTime; }
     80 
     81     void checkConsistency() const;
     82     void checkHeapIndex() const;
     83 
     84     void setNextFireTime(double);
     85 
     86     bool inHeap() const { return m_heapIndex != -1; }
     87 
     88     bool hasValidHeapPosition() const;
     89     void updateHeapIfNeeded(double oldTime);
     90 
     91     void heapDecreaseKey();
     92     void heapDelete();
     93     void heapDeleteMin();
     94     void heapIncreaseKey();
     95     void heapInsert();
     96     void heapPop();
     97     void heapPopMin();
     98 
     99     Vector<TimerBase*>& timerHeap() const { ASSERT(m_cachedThreadGlobalTimerHeap); return *m_cachedThreadGlobalTimerHeap; }
    100 
    101     double m_nextFireTime; // 0 if inactive
    102     double m_unalignedNextFireTime; // m_nextFireTime not considering alignment interval
    103     double m_repeatInterval; // 0 if not repeating
    104     int m_heapIndex; // -1 if not in heap
    105     unsigned m_heapInsertionOrder; // Used to keep order among equal-fire-time timers
    106     Vector<TimerBase*>* m_cachedThreadGlobalTimerHeap;
    107     TraceLocation m_location;
    108 
    109 #ifndef NDEBUG
    110     ThreadIdentifier m_thread;
    111 #endif
    112 
    113     friend class ThreadTimers;
    114     friend class TimerHeapLessThanFunction;
    115     friend class TimerHeapReference;
    116 };
    117 
    118 template <typename TimerFiredClass>
    119 class Timer FINAL : public TimerBase {
    120 public:
    121     typedef void (TimerFiredClass::*TimerFiredFunction)(Timer*);
    122 
    123     Timer(TimerFiredClass* o, TimerFiredFunction f)
    124         : m_object(o), m_function(f) { }
    125 
    126 private:
    127     virtual void fired() OVERRIDE { (m_object->*m_function)(this); }
    128 
    129     // FIXME: oilpan: TimerBase should be moved to the heap and m_object should be traced.
    130     // This raw pointer is safe as long as Timer<X> is held by the X itself (That's the case
    131     // in the current code base).
    132     GC_PLUGIN_IGNORE("363031")
    133     TimerFiredClass* m_object;
    134     TimerFiredFunction m_function;
    135 };
    136 
    137 inline bool TimerBase::isActive() const
    138 {
    139     ASSERT(m_thread == currentThread());
    140     return m_nextFireTime;
    141 }
    142 
    143 template <typename TimerFiredClass>
    144 class DeferrableOneShotTimer FINAL : private TimerBase {
    145 public:
    146     typedef void (TimerFiredClass::*TimerFiredFunction)(DeferrableOneShotTimer*);
    147 
    148     DeferrableOneShotTimer(TimerFiredClass* o, TimerFiredFunction f, double delay)
    149         : m_object(o)
    150         , m_function(f)
    151         , m_delay(delay)
    152         , m_shouldRestartWhenTimerFires(false)
    153     {
    154     }
    155 
    156     void restart(const TraceLocation& caller)
    157     {
    158         // Setting this boolean is much more efficient than calling startOneShot
    159         // again, which might result in rescheduling the system timer which
    160         // can be quite expensive.
    161 
    162         if (isActive()) {
    163             m_shouldRestartWhenTimerFires = true;
    164             return;
    165         }
    166         startOneShot(m_delay, caller);
    167     }
    168 
    169     using TimerBase::stop;
    170     using TimerBase::isActive;
    171 
    172 private:
    173     virtual void fired() OVERRIDE
    174     {
    175         if (m_shouldRestartWhenTimerFires) {
    176             m_shouldRestartWhenTimerFires = false;
    177             // FIXME: This should not be FROM_HERE.
    178             startOneShot(m_delay, FROM_HERE);
    179             return;
    180         }
    181 
    182         (m_object->*m_function)(this);
    183     }
    184 
    185     // FIXME: oilpan: TimerBase should be moved to the heap and m_object should be traced.
    186     // This raw pointer is safe as long as Timer<X> is held by the X itself (That's the case
    187     // in the current code base).
    188     GC_PLUGIN_IGNORE("363031")
    189     TimerFiredClass* m_object;
    190     TimerFiredFunction m_function;
    191 
    192     double m_delay;
    193     bool m_shouldRestartWhenTimerFires;
    194 };
    195 
    196 }
    197 
    198 #endif
    199