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 blink { 37 38 // Time intervals are all in seconds. 39 40 class PLATFORM_EXPORT TimerBase { 41 WTF_MAKE_NONCOPYABLE(TimerBase); WTF_MAKE_FAST_ALLOCATED_WILL_BE_REMOVED; 42 public: 43 TimerBase(); 44 virtual ~TimerBase(); 45 46 void start(double nextFireInterval, double repeatInterval, const TraceLocation&); 47 48 void startRepeating(double repeatInterval, const TraceLocation& caller) 49 { 50 start(repeatInterval, repeatInterval, caller); 51 } 52 void startOneShot(double interval, const TraceLocation& caller) 53 { 54 start(interval, 0, caller); 55 } 56 57 void stop(); 58 bool isActive() const; 59 const TraceLocation& location() const { return m_location; } 60 61 double nextFireInterval() const; 62 double nextUnalignedFireInterval() const; 63 double repeatInterval() const { return m_repeatInterval; } 64 65 void augmentRepeatInterval(double delta) { 66 setNextFireTime(m_nextFireTime + delta); 67 m_repeatInterval += delta; 68 } 69 70 void didChangeAlignmentInterval(); 71 72 static void fireTimersInNestedEventLoop(); 73 74 private: 75 virtual void fired() = 0; 76 77 virtual double alignedFireTime(double fireTime) const { return fireTime; } 78 79 void checkConsistency() const; 80 void checkHeapIndex() const; 81 82 void setNextFireTime(double); 83 84 bool inHeap() const { return m_heapIndex != -1; } 85 86 bool hasValidHeapPosition() const; 87 void updateHeapIfNeeded(double oldTime); 88 89 void heapDecreaseKey(); 90 void heapDelete(); 91 void heapDeleteMin(); 92 void heapIncreaseKey(); 93 void heapInsert(); 94 void heapPop(); 95 void heapPopMin(); 96 97 Vector<TimerBase*>& timerHeap() const { ASSERT(m_cachedThreadGlobalTimerHeap); return *m_cachedThreadGlobalTimerHeap; } 98 99 double m_nextFireTime; // 0 if inactive 100 double m_unalignedNextFireTime; // m_nextFireTime not considering alignment interval 101 double m_repeatInterval; // 0 if not repeating 102 int m_heapIndex; // -1 if not in heap 103 unsigned m_heapInsertionOrder; // Used to keep order among equal-fire-time timers 104 Vector<TimerBase*>* m_cachedThreadGlobalTimerHeap; 105 TraceLocation m_location; 106 107 #if ENABLE(ASSERT) 108 ThreadIdentifier m_thread; 109 #endif 110 111 friend class ThreadTimers; 112 friend class TimerHeapLessThanFunction; 113 friend class TimerHeapReference; 114 }; 115 116 template <typename TimerFiredClass> 117 class Timer FINAL : public TimerBase { 118 public: 119 typedef void (TimerFiredClass::*TimerFiredFunction)(Timer*); 120 121 Timer(TimerFiredClass* o, TimerFiredFunction f) 122 : m_object(o), m_function(f) { } 123 124 private: 125 virtual void fired() OVERRIDE { (m_object->*m_function)(this); } 126 127 // FIXME: oilpan: TimerBase should be moved to the heap and m_object should be traced. 128 // This raw pointer is safe as long as Timer<X> is held by the X itself (That's the case 129 // in the current code base). 130 GC_PLUGIN_IGNORE("363031") 131 TimerFiredClass* m_object; 132 TimerFiredFunction m_function; 133 }; 134 135 inline bool TimerBase::isActive() const 136 { 137 ASSERT(m_thread == currentThread()); 138 return m_nextFireTime; 139 } 140 141 template <typename TimerFiredClass> 142 class DeferrableOneShotTimer FINAL : private TimerBase { 143 public: 144 typedef void (TimerFiredClass::*TimerFiredFunction)(DeferrableOneShotTimer*); 145 146 DeferrableOneShotTimer(TimerFiredClass* o, TimerFiredFunction f, double delay) 147 : m_object(o) 148 , m_function(f) 149 , m_delay(delay) 150 , m_shouldRestartWhenTimerFires(false) 151 { 152 } 153 154 void restart(const TraceLocation& caller) 155 { 156 // Setting this boolean is much more efficient than calling startOneShot 157 // again, which might result in rescheduling the system timer which 158 // can be quite expensive. 159 160 if (isActive()) { 161 m_shouldRestartWhenTimerFires = true; 162 return; 163 } 164 startOneShot(m_delay, caller); 165 } 166 167 using TimerBase::stop; 168 using TimerBase::isActive; 169 170 private: 171 virtual void fired() OVERRIDE 172 { 173 if (m_shouldRestartWhenTimerFires) { 174 m_shouldRestartWhenTimerFires = false; 175 // FIXME: This should not be FROM_HERE. 176 startOneShot(m_delay, FROM_HERE); 177 return; 178 } 179 180 (m_object->*m_function)(this); 181 } 182 183 // FIXME: oilpan: TimerBase should be moved to the heap and m_object should be traced. 184 // This raw pointer is safe as long as Timer<X> is held by the X itself (That's the case 185 // in the current code base). 186 GC_PLUGIN_IGNORE("363031") 187 TimerFiredClass* m_object; 188 TimerFiredFunction m_function; 189 190 double m_delay; 191 bool m_shouldRestartWhenTimerFires; 192 }; 193 194 } 195 196 #endif 197