|
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- |
|
2 * This Source Code Form is subject to the terms of the Mozilla Public |
|
3 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
5 |
|
6 #ifndef nsTimerImpl_h___ |
|
7 #define nsTimerImpl_h___ |
|
8 |
|
9 //#define FORCE_PR_LOG /* Allow logging in the release build */ |
|
10 |
|
11 #include "nsITimer.h" |
|
12 #include "nsIEventTarget.h" |
|
13 #include "nsIObserver.h" |
|
14 |
|
15 #include "nsCOMPtr.h" |
|
16 |
|
17 #include "prlog.h" |
|
18 #include "mozilla/TimeStamp.h" |
|
19 #include "mozilla/Attributes.h" |
|
20 |
|
21 #ifdef MOZ_TASK_TRACER |
|
22 #include "TracedTaskCommon.h" |
|
23 #endif |
|
24 |
|
25 #if defined(PR_LOGGING) |
|
26 extern PRLogModuleInfo *GetTimerLog(); |
|
27 #define DEBUG_TIMERS 1 |
|
28 #else |
|
29 #undef DEBUG_TIMERS |
|
30 #endif |
|
31 |
|
32 #define NS_TIMER_CID \ |
|
33 { /* 5ff24248-1dd2-11b2-8427-fbab44f29bc8 */ \ |
|
34 0x5ff24248, \ |
|
35 0x1dd2, \ |
|
36 0x11b2, \ |
|
37 {0x84, 0x27, 0xfb, 0xab, 0x44, 0xf2, 0x9b, 0xc8} \ |
|
38 } |
|
39 |
|
40 enum { |
|
41 CALLBACK_TYPE_UNKNOWN = 0, |
|
42 CALLBACK_TYPE_INTERFACE = 1, |
|
43 CALLBACK_TYPE_FUNC = 2, |
|
44 CALLBACK_TYPE_OBSERVER = 3 |
|
45 }; |
|
46 |
|
47 class nsTimerImpl MOZ_FINAL : public nsITimer |
|
48 { |
|
49 public: |
|
50 typedef mozilla::TimeStamp TimeStamp; |
|
51 |
|
52 nsTimerImpl(); |
|
53 |
|
54 static NS_HIDDEN_(nsresult) Startup(); |
|
55 static NS_HIDDEN_(void) Shutdown(); |
|
56 |
|
57 friend class TimerThread; |
|
58 friend struct TimerAdditionComparator; |
|
59 |
|
60 void Fire(); |
|
61 // If a failure is encountered, the reference is returned to the caller |
|
62 static already_AddRefed<nsTimerImpl> PostTimerEvent( |
|
63 already_AddRefed<nsTimerImpl> aTimerRef); |
|
64 void SetDelayInternal(uint32_t aDelay); |
|
65 |
|
66 NS_DECL_THREADSAFE_ISUPPORTS |
|
67 NS_DECL_NSITIMER |
|
68 |
|
69 int32_t GetGeneration() { return mGeneration; } |
|
70 |
|
71 #ifdef MOZ_TASK_TRACER |
|
72 void DispatchTracedTask() |
|
73 { |
|
74 mTracedTask = mozilla::tasktracer::CreateFakeTracedTask(*(int**)(this)); |
|
75 } |
|
76 #endif |
|
77 |
|
78 private: |
|
79 ~nsTimerImpl(); |
|
80 nsresult InitCommon(uint32_t aType, uint32_t aDelay); |
|
81 |
|
82 void ReleaseCallback() |
|
83 { |
|
84 // if we're the last owner of the callback object, make |
|
85 // sure that we don't recurse into ReleaseCallback in case |
|
86 // the callback's destructor calls Cancel() or similar. |
|
87 uint8_t cbType = mCallbackType; |
|
88 mCallbackType = CALLBACK_TYPE_UNKNOWN; |
|
89 |
|
90 if (cbType == CALLBACK_TYPE_INTERFACE) |
|
91 NS_RELEASE(mCallback.i); |
|
92 else if (cbType == CALLBACK_TYPE_OBSERVER) |
|
93 NS_RELEASE(mCallback.o); |
|
94 } |
|
95 |
|
96 bool IsRepeating() const { |
|
97 PR_STATIC_ASSERT(TYPE_ONE_SHOT < TYPE_REPEATING_SLACK); |
|
98 PR_STATIC_ASSERT(TYPE_REPEATING_SLACK < TYPE_REPEATING_PRECISE); |
|
99 PR_STATIC_ASSERT(TYPE_REPEATING_PRECISE < TYPE_REPEATING_PRECISE_CAN_SKIP); |
|
100 return mType >= TYPE_REPEATING_SLACK; |
|
101 } |
|
102 |
|
103 bool IsRepeatingPrecisely() const { |
|
104 return mType >= TYPE_REPEATING_PRECISE; |
|
105 } |
|
106 |
|
107 nsCOMPtr<nsIEventTarget> mEventTarget; |
|
108 |
|
109 void * mClosure; |
|
110 |
|
111 union CallbackUnion { |
|
112 nsTimerCallbackFunc c; |
|
113 nsITimerCallback * i; |
|
114 nsIObserver * o; |
|
115 } mCallback; |
|
116 |
|
117 // Some callers expect to be able to access the callback while the |
|
118 // timer is firing. |
|
119 nsCOMPtr<nsITimerCallback> mTimerCallbackWhileFiring; |
|
120 |
|
121 // These members are set by Init (called from NS_NewTimer) and never reset. |
|
122 uint8_t mCallbackType; |
|
123 |
|
124 // These members are set by the initiating thread, when the timer's type is |
|
125 // changed and during the period where it fires on that thread. |
|
126 uint8_t mType; |
|
127 bool mFiring; |
|
128 |
|
129 |
|
130 // Use a bool (int) here to isolate loads and stores of these two members |
|
131 // done on various threads under the protection of TimerThread::mLock, from |
|
132 // loads and stores done on the initiating/type-changing/timer-firing thread |
|
133 // to the above uint8_t/bool members. |
|
134 bool mArmed; |
|
135 bool mCanceled; |
|
136 |
|
137 // The generation number of this timer, re-generated each time the timer is |
|
138 // initialized so one-shot timers can be canceled and re-initialized by the |
|
139 // arming thread without any bad race conditions. |
|
140 int32_t mGeneration; |
|
141 |
|
142 uint32_t mDelay; |
|
143 TimeStamp mTimeout; |
|
144 |
|
145 #ifdef MOZ_TASK_TRACER |
|
146 nsAutoPtr<mozilla::tasktracer::FakeTracedTask> mTracedTask; |
|
147 #endif |
|
148 |
|
149 #ifdef DEBUG_TIMERS |
|
150 TimeStamp mStart, mStart2; |
|
151 static double sDeltaSum; |
|
152 static double sDeltaSumSquared; |
|
153 static double sDeltaNum; |
|
154 #endif |
|
155 |
|
156 }; |
|
157 |
|
158 #endif /* nsTimerImpl_h___ */ |