xpcom/threads/nsThread.h

changeset 0
6474c204b198
equal deleted inserted replaced
-1:000000000000 0:c898e08dc111
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim:set ts=2 sw=2 sts=2 et cindent: */
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 nsThread_h__
8 #define nsThread_h__
9
10 #include "mozilla/Mutex.h"
11 #include "nsIThreadInternal.h"
12 #include "nsISupportsPriority.h"
13 #include "nsEventQueue.h"
14 #include "nsThreadUtils.h"
15 #include "nsString.h"
16 #include "nsTObserverArray.h"
17 #include "mozilla/Attributes.h"
18 #include "nsAutoPtr.h"
19
20 // A native thread
21 class nsThread : public nsIThreadInternal,
22 public nsISupportsPriority
23 {
24 public:
25 NS_DECL_THREADSAFE_ISUPPORTS
26 NS_DECL_NSIEVENTTARGET
27 NS_DECL_NSITHREAD
28 NS_DECL_NSITHREADINTERNAL
29 NS_DECL_NSISUPPORTSPRIORITY
30
31 enum MainThreadFlag {
32 MAIN_THREAD,
33 NOT_MAIN_THREAD
34 };
35
36 nsThread(MainThreadFlag aMainThread, uint32_t aStackSize);
37
38 // Initialize this as a wrapper for a new PRThread.
39 nsresult Init();
40
41 // Initialize this as a wrapper for the current PRThread.
42 nsresult InitCurrentThread();
43
44 // The PRThread corresponding to this thread.
45 PRThread *GetPRThread() { return mThread; }
46
47 // If this flag is true, then the nsThread was created using
48 // nsIThreadManager::NewThread.
49 bool ShutdownRequired() { return mShutdownRequired; }
50
51 // Clear the observer list.
52 void ClearObservers() { mEventObservers.Clear(); }
53
54 static nsresult
55 SetMainThreadObserver(nsIThreadObserver* aObserver);
56
57 protected:
58 static nsIThreadObserver* sMainThreadObserver;
59
60 class nsChainedEventQueue;
61
62 class nsNestedEventTarget;
63 friend class nsNestedEventTarget;
64
65 friend class nsThreadShutdownEvent;
66
67 virtual ~nsThread();
68
69 bool ShuttingDown() { return mShutdownContext != nullptr; }
70
71 static void ThreadFunc(void *arg);
72
73 // Helper
74 already_AddRefed<nsIThreadObserver> GetObserver() {
75 nsIThreadObserver *obs;
76 nsThread::GetObserver(&obs);
77 return already_AddRefed<nsIThreadObserver>(obs);
78 }
79
80 // Wrappers for event queue methods:
81 bool GetEvent(bool mayWait, nsIRunnable **event) {
82 return mEvents->GetEvent(mayWait, event);
83 }
84 nsresult PutEvent(nsIRunnable *event, nsNestedEventTarget *target);
85
86 nsresult DispatchInternal(nsIRunnable *event, uint32_t flags,
87 nsNestedEventTarget *target);
88
89 // Wrapper for nsEventQueue that supports chaining.
90 class nsChainedEventQueue {
91 public:
92 nsChainedEventQueue()
93 : mNext(nullptr) {
94 }
95
96 bool GetEvent(bool mayWait, nsIRunnable **event) {
97 return mQueue.GetEvent(mayWait, event);
98 }
99
100 bool PutEvent(nsIRunnable *event) {
101 return mQueue.PutEvent(event);
102 }
103
104 bool HasPendingEvent() {
105 return mQueue.HasPendingEvent();
106 }
107
108 nsChainedEventQueue *mNext;
109 nsRefPtr<nsNestedEventTarget> mEventTarget;
110
111 private:
112 nsEventQueue mQueue;
113 };
114
115 class nsNestedEventTarget MOZ_FINAL : public nsIEventTarget {
116 public:
117 NS_DECL_THREADSAFE_ISUPPORTS
118 NS_DECL_NSIEVENTTARGET
119
120 nsNestedEventTarget(nsThread *thread, nsChainedEventQueue *queue)
121 : mThread(thread), mQueue(queue) {
122 }
123
124 nsRefPtr<nsThread> mThread;
125
126 // This is protected by mThread->mLock.
127 nsChainedEventQueue* mQueue;
128
129 private:
130 ~nsNestedEventTarget() {}
131 };
132
133 // This lock protects access to mObserver, mEvents and mEventsAreDoomed.
134 // All of those fields are only modified on the thread itself (never from
135 // another thread). This means that we can avoid holding the lock while
136 // using mObserver and mEvents on the thread itself. When calling PutEvent
137 // on mEvents, we have to hold the lock to synchronize with PopEventQueue.
138 mozilla::Mutex mLock;
139
140 nsCOMPtr<nsIThreadObserver> mObserver;
141
142 // Only accessed on the target thread.
143 nsAutoTObserverArray<nsCOMPtr<nsIThreadObserver>, 2> mEventObservers;
144
145 nsChainedEventQueue *mEvents; // never null
146 nsChainedEventQueue mEventsRoot;
147
148 int32_t mPriority;
149 PRThread *mThread;
150 uint32_t mRunningEvent; // counter
151 uint32_t mStackSize;
152
153 struct nsThreadShutdownContext *mShutdownContext;
154
155 bool mShutdownRequired;
156 // Set to true when events posted to this thread will never run.
157 bool mEventsAreDoomed;
158 MainThreadFlag mIsMainThread;
159 };
160
161 //-----------------------------------------------------------------------------
162
163 class nsThreadSyncDispatch : public nsRunnable {
164 public:
165 nsThreadSyncDispatch(nsIThread *origin, nsIRunnable *task)
166 : mOrigin(origin), mSyncTask(task), mResult(NS_ERROR_NOT_INITIALIZED) {
167 }
168
169 bool IsPending() {
170 return mSyncTask != nullptr;
171 }
172
173 nsresult Result() {
174 return mResult;
175 }
176
177 private:
178 NS_DECL_NSIRUNNABLE
179
180 nsCOMPtr<nsIThread> mOrigin;
181 nsCOMPtr<nsIRunnable> mSyncTask;
182 nsresult mResult;
183 };
184
185 #if defined(XP_UNIX) && !defined(ANDROID) && !defined(DEBUG) && HAVE_UALARM \
186 && defined(_GNU_SOURCE)
187 # define MOZ_CANARY
188
189 extern int sCanaryOutputFD;
190 #endif
191
192 #endif // nsThread_h__

mercurial