forked from mirrors/gecko-dev
		
	 f933869f5f
			
		
	
	
		f933869f5f
		
	
	
	
	
		
			
			Some debug infrastructure like MOZ_WEAKPTR_INIT_THREAD_SAFETY_CHECK that can apparently be triggered by nsComponentManagerImpl::gComponentManager->FreeService() seem to rely on the existence of a serial event target even if they do not post any events. So it seems sound to keep a representation of the main thread as nsThread object until after final XPCOM shutdown. But nsThreadManager::ShutdownMainThread() does more, it processes the last round of events, removes the thread's observer and closes down the background event target. We do not want to move these operations to happen later than before, such that we split the nsThread release into a separate function and move that together with AbstractThread::ShutdownMainThread() behind FreeService(). Depends on D160628 Differential Revision: https://phabricator.services.mozilla.com/D162497
		
			
				
	
	
		
			117 lines
		
	
	
	
		
			4.1 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			117 lines
		
	
	
	
		
			4.1 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 | |
| /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 | |
| /* This Source Code Form is subject to the terms of the Mozilla Public
 | |
|  * License, v. 2.0. If a copy of the MPL was not distributed with this
 | |
|  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 | |
| 
 | |
| #ifndef nsThreadManager_h__
 | |
| #define nsThreadManager_h__
 | |
| 
 | |
| #include "nsIThreadManager.h"
 | |
| #include "nsThread.h"
 | |
| #include "mozilla/ShutdownPhase.h"
 | |
| 
 | |
| class nsIRunnable;
 | |
| class nsIEventTarget;
 | |
| class nsISerialEventTarget;
 | |
| class nsIThread;
 | |
| 
 | |
| namespace mozilla {
 | |
| class IdleTaskManager;
 | |
| class SynchronizedEventQueue;
 | |
| }  // namespace mozilla
 | |
| 
 | |
| class BackgroundEventTarget;
 | |
| 
 | |
| class nsThreadManager : public nsIThreadManager {
 | |
|  public:
 | |
|   NS_DECL_ISUPPORTS
 | |
|   NS_DECL_NSITHREADMANAGER
 | |
| 
 | |
|   static nsThreadManager& get();
 | |
| 
 | |
|   nsresult Init();
 | |
| 
 | |
|   // Shutdown all threads other than the main thread.  This function should only
 | |
|   // be called on the main thread of the application process.
 | |
|   void ShutdownNonMainThreads();
 | |
| 
 | |
|   // Finish shutting down all threads. This function must be called after
 | |
|   // ShutdownNonMainThreads and will delete the BackgroundEventTarget and
 | |
|   // take the main thread event target out of commission, but without
 | |
|   // releasing the underlying nsThread object.
 | |
|   void ShutdownMainThread();
 | |
| 
 | |
|   // Release the underlying main thread nsThread object.
 | |
|   void ReleaseMainThread();
 | |
| 
 | |
|   // Called by nsThread to inform the ThreadManager it exists.  This method
 | |
|   // must be called when the given thread is the current thread.
 | |
|   void RegisterCurrentThread(nsThread& aThread);
 | |
| 
 | |
|   // Called by nsThread to inform the ThreadManager it is going away.  This
 | |
|   // method must be called when the given thread is the current thread.
 | |
|   void UnregisterCurrentThread(nsThread& aThread);
 | |
| 
 | |
|   // Returns the current thread.  Returns null if OOM or if ThreadManager isn't
 | |
|   // initialized.  Creates the nsThread if one does not exist yet.
 | |
|   nsThread* GetCurrentThread();
 | |
| 
 | |
|   // Returns true iff the currently running thread has an nsThread associated
 | |
|   // with it (ie; whether this is a thread that we can dispatch runnables to).
 | |
|   bool IsNSThread() const;
 | |
| 
 | |
|   // CreateCurrentThread sets up an nsThread for the current thread. It uses the
 | |
|   // event queue and main thread flags passed in. It should only be called once
 | |
|   // for the current thread. After it returns, GetCurrentThread() will return
 | |
|   // the thread that was created. GetCurrentThread() will also create a thread
 | |
|   // (lazily), but it doesn't allow the queue or main-thread attributes to be
 | |
|   // specified.
 | |
|   nsThread* CreateCurrentThread(mozilla::SynchronizedEventQueue* aQueue,
 | |
|                                 nsThread::MainThreadFlag aMainThread);
 | |
| 
 | |
|   nsresult DispatchToBackgroundThread(nsIRunnable* aEvent,
 | |
|                                       uint32_t aDispatchFlags);
 | |
| 
 | |
|   already_AddRefed<nsISerialEventTarget> CreateBackgroundTaskQueue(
 | |
|       const char* aName);
 | |
| 
 | |
|   ~nsThreadManager();
 | |
| 
 | |
|   void EnableMainThreadEventPrioritization();
 | |
|   void FlushInputEventPrioritization();
 | |
|   void SuspendInputEventPrioritization();
 | |
|   void ResumeInputEventPrioritization();
 | |
| 
 | |
|   static bool MainThreadHasPendingHighPriorityEvents();
 | |
| 
 | |
|   nsIThread* GetMainThreadWeak() { return mMainThread; }
 | |
| 
 | |
|  private:
 | |
|   nsThreadManager();
 | |
| 
 | |
|   nsresult SpinEventLoopUntilInternal(
 | |
|       const nsACString& aVeryGoodReasonToDoThis,
 | |
|       nsINestedEventLoopCondition* aCondition,
 | |
|       mozilla::ShutdownPhase aShutdownPhaseToCheck);
 | |
| 
 | |
|   static void ReleaseThread(void* aData);
 | |
| 
 | |
|   unsigned mCurThreadIndex;  // thread-local-storage index
 | |
|   RefPtr<mozilla::IdleTaskManager> mIdleTaskManager;
 | |
|   RefPtr<nsThread> mMainThread;
 | |
|   PRThread* mMainPRThread;
 | |
|   mozilla::Atomic<bool, mozilla::SequentiallyConsistent> mInitialized;
 | |
| 
 | |
|   // Shared event target used for background runnables.
 | |
|   RefPtr<BackgroundEventTarget> mBackgroundEventTarget;
 | |
| };
 | |
| 
 | |
| #define NS_THREADMANAGER_CID                         \
 | |
|   { /* 7a4204c6-e45a-4c37-8ebb-6709a22c917c */       \
 | |
|     0x7a4204c6, 0xe45a, 0x4c37, {                    \
 | |
|       0x8e, 0xbb, 0x67, 0x09, 0xa2, 0x2c, 0x91, 0x7c \
 | |
|     }                                                \
 | |
|   }
 | |
| 
 | |
| #endif  // nsThreadManager_h__
 |