xpcom/threads/nsThread.h

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

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

mercurial