mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-03-01 13:57:32 +00:00
Bug 1450059 - part 1 - add a NS_DispatchToBackgroundThread function; r=KrisWright
We have a number of people starting up singleton threads for the sole purpose of running a single runnable on them. These consumers often leave the thread running until some point close to shutdown, or they never shut it down at all. Let's add a helper function to do the thing they actually want to do, and then we can modify the implementation of that function as necessary as we merge singleton threads (and even thread pools) together. Differential Revision: https://phabricator.services.mozilla.com/D46997 --HG-- extra : moz-landing-system : lando
This commit is contained in:
parent
a0da738473
commit
ec1207f341
@ -6,6 +6,7 @@
|
||||
|
||||
#include "nsThreadManager.h"
|
||||
#include "nsThread.h"
|
||||
#include "nsThreadPool.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "nsIClassInfoImpl.h"
|
||||
#include "nsTArray.h"
|
||||
@ -194,6 +195,12 @@ void nsThreadManager::InitializeShutdownObserver() {
|
||||
ClearOnShutdown(&gShutdownObserveHelper);
|
||||
}
|
||||
|
||||
nsThreadManager::nsThreadManager()
|
||||
: mCurThreadIndex(0),
|
||||
mMainPRThread(nullptr),
|
||||
mInitialized(false)
|
||||
{}
|
||||
|
||||
nsresult nsThreadManager::Init() {
|
||||
// Child processes need to initialize the thread manager before they
|
||||
// initialize XPCOM in order to set up the crash reporter. This leads to
|
||||
@ -239,6 +246,27 @@ nsresult nsThreadManager::Init() {
|
||||
AbstractThread::InitTLS();
|
||||
AbstractThread::InitMainThread();
|
||||
|
||||
// Initialize the background event target.
|
||||
nsCOMPtr<nsIThreadPool> pool(new nsThreadPool());
|
||||
NS_ENSURE_TRUE(pool, NS_ERROR_FAILURE);
|
||||
|
||||
rv = pool->SetName(NS_LITERAL_CSTRING("BackgroundThreadPool"));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Use potentially more conservative stack size.
|
||||
rv = pool->SetThreadStackSize(nsIThreadManager::kThreadPoolStackSize);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// For now just one thread. Can increase easily later if we want.
|
||||
rv = pool->SetThreadLimit(1);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Leave threads alive for up to 5 minutes
|
||||
rv = pool->SetIdleThreadTimeout(300000);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
pool.swap(mBackgroundEventTarget);
|
||||
|
||||
mInitialized = true;
|
||||
|
||||
return NS_OK;
|
||||
@ -259,6 +287,8 @@ void nsThreadManager::Shutdown() {
|
||||
// Empty the main thread event queue before we begin shutting down threads.
|
||||
NS_ProcessPendingEvents(mMainThread);
|
||||
|
||||
mBackgroundEventTarget->Shutdown();
|
||||
|
||||
{
|
||||
// We gather the threads from the hashtable into a list, so that we avoid
|
||||
// holding the enumerator lock while calling nsIThread::Shutdown.
|
||||
@ -300,6 +330,8 @@ void nsThreadManager::Shutdown() {
|
||||
// have been processed.
|
||||
mMainThread->SetObserver(nullptr);
|
||||
|
||||
mBackgroundEventTarget = nullptr;
|
||||
|
||||
// Release main thread object.
|
||||
mMainThread = nullptr;
|
||||
|
||||
@ -357,6 +389,16 @@ nsThread* nsThreadManager::CreateCurrentThread(
|
||||
return thread.get(); // reference held in TLS
|
||||
}
|
||||
|
||||
nsresult nsThreadManager::DispatchToBackgroundThread(nsIRunnable* aEvent,
|
||||
uint32_t aDispatchFlags) {
|
||||
if (!mInitialized) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIThreadPool> backgroundTarget(mBackgroundEventTarget);
|
||||
return backgroundTarget->Dispatch(aEvent, aDispatchFlags);
|
||||
}
|
||||
|
||||
nsThread* nsThreadManager::GetCurrentThread() {
|
||||
// read thread local storage
|
||||
void* data = PR_GetThreadPrivate(mCurThreadIndex);
|
||||
|
@ -9,6 +9,7 @@
|
||||
|
||||
#include "mozilla/Mutex.h"
|
||||
#include "nsIThreadManager.h"
|
||||
#include "nsIThreadPool.h"
|
||||
#include "nsThread.h"
|
||||
|
||||
class nsIRunnable;
|
||||
@ -53,6 +54,9 @@ class nsThreadManager : public nsIThreadManager {
|
||||
nsThread* CreateCurrentThread(mozilla::SynchronizedEventQueue* aQueue,
|
||||
nsThread::MainThreadFlag aMainThread);
|
||||
|
||||
nsresult DispatchToBackgroundThread(nsIRunnable* aEvent,
|
||||
uint32_t aDispatchFlags);
|
||||
|
||||
// Returns the maximal number of threads that have been in existence
|
||||
// simultaneously during the execution of the thread manager.
|
||||
uint32_t GetHighestNumberOfThreads();
|
||||
@ -69,8 +73,7 @@ class nsThreadManager : public nsIThreadManager {
|
||||
static bool MainThreadHasPendingHighPriorityEvents();
|
||||
|
||||
private:
|
||||
nsThreadManager()
|
||||
: mCurThreadIndex(0), mMainPRThread(nullptr), mInitialized(false) {}
|
||||
nsThreadManager();
|
||||
|
||||
nsresult SpinEventLoopUntilInternal(nsINestedEventLoopCondition* aCondition,
|
||||
bool aCheckingShutdown);
|
||||
@ -83,6 +86,9 @@ class nsThreadManager : public nsIThreadManager {
|
||||
mozilla::Atomic<bool, mozilla::SequentiallyConsistent,
|
||||
mozilla::recordreplay::Behavior::DontPreserve>
|
||||
mInitialized;
|
||||
|
||||
// Shared event target used for background runnables.
|
||||
nsCOMPtr<nsIThreadPool> mBackgroundEventTarget;
|
||||
};
|
||||
|
||||
#define NS_THREADMANAGER_CID \
|
||||
|
@ -518,6 +518,17 @@ nsCString nsThreadPoolNaming::GetNextThreadName(const nsACString& aPoolName) {
|
||||
return name;
|
||||
}
|
||||
|
||||
nsresult NS_DispatchToBackgroundThread(already_AddRefed<nsIRunnable> aEvent,
|
||||
uint32_t aDispatchFlags) {
|
||||
nsCOMPtr<nsIRunnable> event(aEvent);
|
||||
return nsThreadManager::get().DispatchToBackgroundThread(event, aDispatchFlags);
|
||||
}
|
||||
|
||||
nsresult NS_DispatchToBackgroundThread(nsIRunnable* aEvent,
|
||||
uint32_t aDispatchFlags) {
|
||||
return nsThreadManager::get().DispatchToBackgroundThread(aEvent, aDispatchFlags);
|
||||
}
|
||||
|
||||
// nsAutoLowPriorityIO
|
||||
nsAutoLowPriorityIO::nsAutoLowPriorityIO() {
|
||||
#if defined(XP_WIN)
|
||||
|
@ -1693,6 +1693,19 @@ void NS_UnsetMainThread();
|
||||
extern mozilla::TimeStamp NS_GetTimerDeadlineHintOnCurrentThread(
|
||||
mozilla::TimeStamp aDefault, uint32_t aSearchBound);
|
||||
|
||||
/**
|
||||
* Dispatches the given event to a background thread. The primary benefit of
|
||||
* this API is that you do not have to manage the lifetime of your own thread
|
||||
* for running your own events; the thread manager will take care of the
|
||||
* background thread's lifetime. Not having to manage your own thread also
|
||||
* means less resource usage, as the underlying implementation here can manage
|
||||
* spinning up and shutting down threads appropriately.
|
||||
*/
|
||||
extern nsresult NS_DispatchToBackgroundThread(already_AddRefed<nsIRunnable> aEvent,
|
||||
uint32_t aDispatchFlags = NS_DISPATCH_NORMAL);
|
||||
extern nsresult NS_DispatchToBackgroundThread(nsIRunnable* aEvent,
|
||||
uint32_t aDispatchFlags = NS_DISPATCH_NORMAL);
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
/**
|
||||
|
Loading…
x
Reference in New Issue
Block a user