xpcom/threads/LazyIdleThread.h

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

mercurial