/src/mozilla-central/xpcom/threads/LazyIdleThread.h
Line | Count | Source (jump to first uncovered line) |
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 mozilla_lazyidlethread_h__ |
8 | | #define mozilla_lazyidlethread_h__ |
9 | | |
10 | | #ifndef MOZILLA_INTERNAL_API |
11 | | #error "This header is only usable from within libxul (MOZILLA_INTERNAL_API)." |
12 | | #endif |
13 | | |
14 | | #include "nsINamed.h" |
15 | | #include "nsIObserver.h" |
16 | | #include "nsIThreadInternal.h" |
17 | | #include "nsITimer.h" |
18 | | |
19 | | #include "mozilla/Mutex.h" |
20 | | #include "nsCOMPtr.h" |
21 | | #include "nsTArray.h" |
22 | | #include "nsString.h" |
23 | | #include "mozilla/Attributes.h" |
24 | | |
25 | 0 | #define IDLE_THREAD_TOPIC "thread-shutting-down" |
26 | | |
27 | | namespace mozilla { |
28 | | |
29 | | /** |
30 | | * This class provides a basic event target that creates its thread lazily and |
31 | | * destroys its thread after a period of inactivity. It may be created on any |
32 | | * thread but it may only be used from the thread on which it is created. If it |
33 | | * is created on the main thread then it will automatically join its thread on |
34 | | * XPCOM shutdown using the Observer Service. |
35 | | */ |
36 | | class LazyIdleThread final |
37 | | : public nsIThread |
38 | | , public nsITimerCallback |
39 | | , public nsIThreadObserver |
40 | | , public nsIObserver |
41 | | , public nsINamed |
42 | | { |
43 | | public: |
44 | | NS_DECL_THREADSAFE_ISUPPORTS |
45 | | NS_DECL_NSIEVENTTARGET_FULL |
46 | | NS_DECL_NSITHREAD |
47 | | NS_DECL_NSITIMERCALLBACK |
48 | | NS_DECL_NSITHREADOBSERVER |
49 | | NS_DECL_NSIOBSERVER |
50 | | NS_DECL_NSINAMED |
51 | | |
52 | | enum ShutdownMethod |
53 | | { |
54 | | AutomaticShutdown = 0, |
55 | | ManualShutdown |
56 | | }; |
57 | | |
58 | | /** |
59 | | * Create a new LazyIdleThread that will destroy its thread after the given |
60 | | * number of milliseconds. |
61 | | */ |
62 | | LazyIdleThread(uint32_t aIdleTimeoutMS, |
63 | | const nsACString& aName, |
64 | | ShutdownMethod aShutdownMethod = AutomaticShutdown, |
65 | | nsIObserver* aIdleObserver = nullptr); |
66 | | |
67 | | /** |
68 | | * Add an observer that will be notified when the thread is idle and about to |
69 | | * be shut down. The aSubject argument can be QueryInterface'd to an nsIThread |
70 | | * that can be used to post cleanup events. The aTopic argument will be |
71 | | * IDLE_THREAD_TOPIC, and aData will be null. The LazyIdleThread does not add |
72 | | * a reference to the observer to avoid circular references as it is assumed |
73 | | * to be the owner. It is the caller's responsibility to clear this observer |
74 | | * if the pointer becomes invalid. |
75 | | */ |
76 | | void SetWeakIdleObserver(nsIObserver* aObserver); |
77 | | |
78 | | /** |
79 | | * Disable the idle timeout for this thread. No effect if the timeout is |
80 | | * already disabled. |
81 | | */ |
82 | | void DisableIdleTimeout(); |
83 | | |
84 | | /** |
85 | | * Enable the idle timeout. No effect if the timeout is already enabled. |
86 | | */ |
87 | | void EnableIdleTimeout(); |
88 | | |
89 | | private: |
90 | | /** |
91 | | * Calls Shutdown(). |
92 | | */ |
93 | | ~LazyIdleThread(); |
94 | | |
95 | | /** |
96 | | * Called just before dispatching to mThread. |
97 | | */ |
98 | | void PreDispatch(); |
99 | | |
100 | | /** |
101 | | * Makes sure a valid thread lives in mThread. |
102 | | */ |
103 | | nsresult EnsureThread(); |
104 | | |
105 | | /** |
106 | | * Called on mThread to set up the thread observer. |
107 | | */ |
108 | | void InitThread(); |
109 | | |
110 | | /** |
111 | | * Called on mThread to clean up the thread observer. |
112 | | */ |
113 | | void CleanupThread(); |
114 | | |
115 | | /** |
116 | | * Called on the main thread when mThread believes itself to be idle. Sets up |
117 | | * the idle timer. |
118 | | */ |
119 | | void ScheduleTimer(); |
120 | | |
121 | | /** |
122 | | * Called when we are shutting down mThread. |
123 | | */ |
124 | | nsresult ShutdownThread(); |
125 | | |
126 | | /** |
127 | | * Deletes this object. Used to delay calling mThread->Shutdown() during the |
128 | | * final release (during a GC, for instance). |
129 | | */ |
130 | | void SelfDestruct(); |
131 | | |
132 | | /** |
133 | | * Returns true if events should be queued rather than immediately dispatched |
134 | | * to mThread. Currently only happens when the thread is shutting down. |
135 | | */ |
136 | | bool UseRunnableQueue() |
137 | 0 | { |
138 | 0 | return !!mQueuedRunnables; |
139 | 0 | } |
140 | | |
141 | | /** |
142 | | * Protects data that is accessed on both threads. |
143 | | */ |
144 | | mozilla::Mutex mMutex; |
145 | | |
146 | | /** |
147 | | * Touched on both threads but set before mThread is created. Used to direct |
148 | | * timer events to the owning thread. |
149 | | */ |
150 | | nsCOMPtr<nsISerialEventTarget> mOwningEventTarget; |
151 | | |
152 | | /** |
153 | | * Only accessed on the owning thread. Set by EnsureThread(). |
154 | | */ |
155 | | nsCOMPtr<nsIThread> mThread; |
156 | | |
157 | | /** |
158 | | * Protected by mMutex. Created when mThread has no pending events and fired |
159 | | * at mOwningThread. Any thread that dispatches to mThread will take ownership |
160 | | * of the timer and fire a separate cancel event to the owning thread. |
161 | | */ |
162 | | nsCOMPtr<nsITimer> mIdleTimer; |
163 | | |
164 | | /** |
165 | | * Idle observer. Called when the thread is about to be shut down. Released |
166 | | * only when Shutdown() is called. |
167 | | */ |
168 | | nsIObserver* MOZ_UNSAFE_REF("See the documentation for SetWeakIdleObserver for " |
169 | | "how the owner of LazyIdleThread should manage the " |
170 | | "lifetime information of this field") mIdleObserver; |
171 | | |
172 | | /** |
173 | | * Temporary storage for events that happen to be dispatched while we're in |
174 | | * the process of shutting down our real thread. |
175 | | */ |
176 | | nsTArray<nsCOMPtr<nsIRunnable>>* mQueuedRunnables; |
177 | | |
178 | | /** |
179 | | * The number of milliseconds a thread should be idle before dying. |
180 | | */ |
181 | | const uint32_t mIdleTimeoutMS; |
182 | | |
183 | | /** |
184 | | * The number of events that are pending on mThread. A nonzero value means |
185 | | * that the thread cannot be cleaned up. |
186 | | */ |
187 | | uint32_t mPendingEventCount; |
188 | | |
189 | | /** |
190 | | * The number of times that mThread has dispatched an idle notification. Any |
191 | | * timer that fires while this count is nonzero can safely be ignored as |
192 | | * another timer will be on the way. |
193 | | */ |
194 | | uint32_t mIdleNotificationCount; |
195 | | |
196 | | /** |
197 | | * Whether or not the thread should automatically shutdown. If the owner |
198 | | * specified ManualShutdown at construction time then the owner should take |
199 | | * care to call Shutdown() manually when appropriate. |
200 | | */ |
201 | | ShutdownMethod mShutdownMethod; |
202 | | |
203 | | /** |
204 | | * Only accessed on the owning thread. Set to true when Shutdown() has been |
205 | | * called and prevents EnsureThread() from recreating mThread. |
206 | | */ |
207 | | bool mShutdown; |
208 | | |
209 | | /** |
210 | | * Set from CleanupThread and lasting until the thread has shut down. Prevents |
211 | | * further idle notifications during the shutdown process. |
212 | | */ |
213 | | bool mThreadIsShuttingDown; |
214 | | |
215 | | /** |
216 | | * Whether or not the idle timeout is enabled. |
217 | | */ |
218 | | bool mIdleTimeoutEnabled; |
219 | | |
220 | | /** |
221 | | * Name of the thread, set on the actual thread after it gets created. |
222 | | */ |
223 | | nsCString mName; |
224 | | }; |
225 | | |
226 | | } // namespace mozilla |
227 | | |
228 | | #endif // mozilla_lazyidlethread_h__ |