Line data Source code
1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 : /* This Source Code Form is subject to the terms of the Mozilla Public
4 : * License, v. 2.0. If a copy of the MPL was not distributed with this
5 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 :
7 : #ifndef TimerThread_h___
8 : #define TimerThread_h___
9 :
10 : #include "nsIObserver.h"
11 : #include "nsIRunnable.h"
12 : #include "nsIThread.h"
13 :
14 : #include "nsTimerImpl.h"
15 : #include "nsThreadUtils.h"
16 :
17 : #include "nsTArray.h"
18 :
19 : #include "mozilla/Atomics.h"
20 : #include "mozilla/Attributes.h"
21 : #include "mozilla/Monitor.h"
22 :
23 : #include <algorithm>
24 :
25 : namespace mozilla {
26 : class TimeStamp;
27 : } // namespace mozilla
28 :
29 : class TimerThread final
30 : : public nsIRunnable
31 : , public nsIObserver
32 : {
33 : public:
34 : typedef mozilla::Monitor Monitor;
35 : typedef mozilla::TimeStamp TimeStamp;
36 : typedef mozilla::TimeDuration TimeDuration;
37 :
38 : TimerThread();
39 : nsresult InitLocks();
40 :
41 : NS_DECL_THREADSAFE_ISUPPORTS
42 : NS_DECL_NSIRUNNABLE
43 : NS_DECL_NSIOBSERVER
44 :
45 : nsresult Shutdown();
46 :
47 : nsresult AddTimer(nsTimerImpl* aTimer);
48 : nsresult RemoveTimer(nsTimerImpl* aTimer);
49 : TimeStamp FindNextFireTimeForCurrentThread(TimeStamp aDefault, uint32_t aSearchBound);
50 :
51 : void DoBeforeSleep();
52 : void DoAfterSleep();
53 :
54 : bool IsOnTimerThread() const
55 : {
56 : return mThread->SerialEventTarget()->IsOnCurrentThread();
57 : }
58 :
59 : uint32_t
60 : AllowedEarlyFiringMicroseconds() const;
61 :
62 : private:
63 : ~TimerThread();
64 :
65 : bool mInitialized;
66 :
67 : // These internal helper methods must be called while mMonitor is held.
68 : // AddTimerInternal returns false if the insertion failed.
69 : bool AddTimerInternal(nsTimerImpl* aTimer);
70 : bool RemoveTimerInternal(nsTimerImpl* aTimer);
71 : void RemoveLeadingCanceledTimersInternal();
72 : void RemoveFirstTimerInternal();
73 : nsresult Init();
74 :
75 : already_AddRefed<nsTimerImpl> PostTimerEvent(already_AddRefed<nsTimerImpl> aTimerRef);
76 :
77 : nsCOMPtr<nsIThread> mThread;
78 : Monitor mMonitor;
79 :
80 : bool mShutdown;
81 : bool mWaiting;
82 : bool mNotified;
83 : bool mSleeping;
84 :
85 180 : class Entry final : public nsTimerImplHolder
86 : {
87 : const TimeStamp mTimeout;
88 :
89 : public:
90 306 : Entry(const TimeStamp& aMinTimeout, const TimeStamp& aTimeout,
91 : nsTimerImpl* aTimerImpl)
92 306 : : nsTimerImplHolder(aTimerImpl)
93 306 : , mTimeout(std::max(aMinTimeout, aTimeout))
94 : {
95 306 : }
96 :
97 : nsTimerImpl*
98 1804 : Value() const
99 : {
100 1804 : return mTimerImpl;
101 : }
102 :
103 : already_AddRefed<nsTimerImpl>
104 90 : Take()
105 : {
106 90 : if (mTimerImpl) {
107 90 : mTimerImpl->SetHolder(nullptr);
108 : }
109 90 : return mTimerImpl.forget();
110 : }
111 :
112 : static bool
113 2013 : UniquePtrLessThan(UniquePtr<Entry>& aLeft, UniquePtr<Entry>& aRight)
114 : {
115 : // This is reversed because std::push_heap() sorts the "largest" to
116 : // the front of the heap. We want that to be the earliest timer.
117 2013 : return aRight->mTimeout < aLeft->mTimeout;
118 : }
119 :
120 477 : TimeStamp Timeout() const
121 : {
122 477 : return mTimeout;
123 : }
124 : };
125 :
126 : nsTArray<UniquePtr<Entry>> mTimers;
127 : uint32_t mAllowedEarlyFiringMicroseconds;
128 : };
129 :
130 : struct TimerAdditionComparator
131 : {
132 : TimerAdditionComparator(const mozilla::TimeStamp& aNow,
133 : nsTimerImpl* aTimerToInsert) :
134 : now(aNow)
135 : #ifdef DEBUG
136 : , timerToInsert(aTimerToInsert)
137 : #endif
138 : {
139 : }
140 :
141 : bool LessThan(nsTimerImpl* aFromArray, nsTimerImpl* aNewTimer) const
142 : {
143 : MOZ_ASSERT(aNewTimer == timerToInsert, "Unexpected timer ordering");
144 :
145 : // Skip any overdue timers.
146 : return aFromArray->mTimeout <= now ||
147 : aFromArray->mTimeout <= aNewTimer->mTimeout;
148 : }
149 :
150 : bool Equals(nsTimerImpl* aFromArray, nsTimerImpl* aNewTimer) const
151 : {
152 : return false;
153 : }
154 :
155 : private:
156 : const mozilla::TimeStamp& now;
157 : #ifdef DEBUG
158 : const nsTimerImpl* const timerToInsert;
159 : #endif
160 : };
161 :
162 : #endif /* TimerThread_h___ */
|