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