1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/xpcom/threads/nsThread.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,192 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* vim:set ts=2 sw=2 sts=2 et cindent: */ 1.6 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 + 1.10 +#ifndef nsThread_h__ 1.11 +#define nsThread_h__ 1.12 + 1.13 +#include "mozilla/Mutex.h" 1.14 +#include "nsIThreadInternal.h" 1.15 +#include "nsISupportsPriority.h" 1.16 +#include "nsEventQueue.h" 1.17 +#include "nsThreadUtils.h" 1.18 +#include "nsString.h" 1.19 +#include "nsTObserverArray.h" 1.20 +#include "mozilla/Attributes.h" 1.21 +#include "nsAutoPtr.h" 1.22 + 1.23 +// A native thread 1.24 +class nsThread : public nsIThreadInternal, 1.25 + public nsISupportsPriority 1.26 +{ 1.27 +public: 1.28 + NS_DECL_THREADSAFE_ISUPPORTS 1.29 + NS_DECL_NSIEVENTTARGET 1.30 + NS_DECL_NSITHREAD 1.31 + NS_DECL_NSITHREADINTERNAL 1.32 + NS_DECL_NSISUPPORTSPRIORITY 1.33 + 1.34 + enum MainThreadFlag { 1.35 + MAIN_THREAD, 1.36 + NOT_MAIN_THREAD 1.37 + }; 1.38 + 1.39 + nsThread(MainThreadFlag aMainThread, uint32_t aStackSize); 1.40 + 1.41 + // Initialize this as a wrapper for a new PRThread. 1.42 + nsresult Init(); 1.43 + 1.44 + // Initialize this as a wrapper for the current PRThread. 1.45 + nsresult InitCurrentThread(); 1.46 + 1.47 + // The PRThread corresponding to this thread. 1.48 + PRThread *GetPRThread() { return mThread; } 1.49 + 1.50 + // If this flag is true, then the nsThread was created using 1.51 + // nsIThreadManager::NewThread. 1.52 + bool ShutdownRequired() { return mShutdownRequired; } 1.53 + 1.54 + // Clear the observer list. 1.55 + void ClearObservers() { mEventObservers.Clear(); } 1.56 + 1.57 + static nsresult 1.58 + SetMainThreadObserver(nsIThreadObserver* aObserver); 1.59 + 1.60 +protected: 1.61 + static nsIThreadObserver* sMainThreadObserver; 1.62 + 1.63 + class nsChainedEventQueue; 1.64 + 1.65 + class nsNestedEventTarget; 1.66 + friend class nsNestedEventTarget; 1.67 + 1.68 + friend class nsThreadShutdownEvent; 1.69 + 1.70 + virtual ~nsThread(); 1.71 + 1.72 + bool ShuttingDown() { return mShutdownContext != nullptr; } 1.73 + 1.74 + static void ThreadFunc(void *arg); 1.75 + 1.76 + // Helper 1.77 + already_AddRefed<nsIThreadObserver> GetObserver() { 1.78 + nsIThreadObserver *obs; 1.79 + nsThread::GetObserver(&obs); 1.80 + return already_AddRefed<nsIThreadObserver>(obs); 1.81 + } 1.82 + 1.83 + // Wrappers for event queue methods: 1.84 + bool GetEvent(bool mayWait, nsIRunnable **event) { 1.85 + return mEvents->GetEvent(mayWait, event); 1.86 + } 1.87 + nsresult PutEvent(nsIRunnable *event, nsNestedEventTarget *target); 1.88 + 1.89 + nsresult DispatchInternal(nsIRunnable *event, uint32_t flags, 1.90 + nsNestedEventTarget *target); 1.91 + 1.92 + // Wrapper for nsEventQueue that supports chaining. 1.93 + class nsChainedEventQueue { 1.94 + public: 1.95 + nsChainedEventQueue() 1.96 + : mNext(nullptr) { 1.97 + } 1.98 + 1.99 + bool GetEvent(bool mayWait, nsIRunnable **event) { 1.100 + return mQueue.GetEvent(mayWait, event); 1.101 + } 1.102 + 1.103 + bool PutEvent(nsIRunnable *event) { 1.104 + return mQueue.PutEvent(event); 1.105 + } 1.106 + 1.107 + bool HasPendingEvent() { 1.108 + return mQueue.HasPendingEvent(); 1.109 + } 1.110 + 1.111 + nsChainedEventQueue *mNext; 1.112 + nsRefPtr<nsNestedEventTarget> mEventTarget; 1.113 + 1.114 + private: 1.115 + nsEventQueue mQueue; 1.116 + }; 1.117 + 1.118 + class nsNestedEventTarget MOZ_FINAL : public nsIEventTarget { 1.119 + public: 1.120 + NS_DECL_THREADSAFE_ISUPPORTS 1.121 + NS_DECL_NSIEVENTTARGET 1.122 + 1.123 + nsNestedEventTarget(nsThread *thread, nsChainedEventQueue *queue) 1.124 + : mThread(thread), mQueue(queue) { 1.125 + } 1.126 + 1.127 + nsRefPtr<nsThread> mThread; 1.128 + 1.129 + // This is protected by mThread->mLock. 1.130 + nsChainedEventQueue* mQueue; 1.131 + 1.132 + private: 1.133 + ~nsNestedEventTarget() {} 1.134 + }; 1.135 + 1.136 + // This lock protects access to mObserver, mEvents and mEventsAreDoomed. 1.137 + // All of those fields are only modified on the thread itself (never from 1.138 + // another thread). This means that we can avoid holding the lock while 1.139 + // using mObserver and mEvents on the thread itself. When calling PutEvent 1.140 + // on mEvents, we have to hold the lock to synchronize with PopEventQueue. 1.141 + mozilla::Mutex mLock; 1.142 + 1.143 + nsCOMPtr<nsIThreadObserver> mObserver; 1.144 + 1.145 + // Only accessed on the target thread. 1.146 + nsAutoTObserverArray<nsCOMPtr<nsIThreadObserver>, 2> mEventObservers; 1.147 + 1.148 + nsChainedEventQueue *mEvents; // never null 1.149 + nsChainedEventQueue mEventsRoot; 1.150 + 1.151 + int32_t mPriority; 1.152 + PRThread *mThread; 1.153 + uint32_t mRunningEvent; // counter 1.154 + uint32_t mStackSize; 1.155 + 1.156 + struct nsThreadShutdownContext *mShutdownContext; 1.157 + 1.158 + bool mShutdownRequired; 1.159 + // Set to true when events posted to this thread will never run. 1.160 + bool mEventsAreDoomed; 1.161 + MainThreadFlag mIsMainThread; 1.162 +}; 1.163 + 1.164 +//----------------------------------------------------------------------------- 1.165 + 1.166 +class nsThreadSyncDispatch : public nsRunnable { 1.167 +public: 1.168 + nsThreadSyncDispatch(nsIThread *origin, nsIRunnable *task) 1.169 + : mOrigin(origin), mSyncTask(task), mResult(NS_ERROR_NOT_INITIALIZED) { 1.170 + } 1.171 + 1.172 + bool IsPending() { 1.173 + return mSyncTask != nullptr; 1.174 + } 1.175 + 1.176 + nsresult Result() { 1.177 + return mResult; 1.178 + } 1.179 + 1.180 +private: 1.181 + NS_DECL_NSIRUNNABLE 1.182 + 1.183 + nsCOMPtr<nsIThread> mOrigin; 1.184 + nsCOMPtr<nsIRunnable> mSyncTask; 1.185 + nsresult mResult; 1.186 +}; 1.187 + 1.188 +#if defined(XP_UNIX) && !defined(ANDROID) && !defined(DEBUG) && HAVE_UALARM \ 1.189 + && defined(_GNU_SOURCE) 1.190 +# define MOZ_CANARY 1.191 + 1.192 +extern int sCanaryOutputFD; 1.193 +#endif 1.194 + 1.195 +#endif // nsThread_h__