1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
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/. */
7 #include "LazyIdleThread.h"
9 #include "nsIObserverService.h"
10 #include "nsServiceManagerUtils.h"
11 #include "nsThreadUtils.h"
14 # define ASSERT_OWNING_THREAD() \
16 MOZ_ASSERT(mOwningEventTarget->IsOnCurrentThread()); \
19 # define ASSERT_OWNING_THREAD() /* nothing */
24 LazyIdleThread::LazyIdleThread(uint32_t aIdleTimeoutMS
, const char* aName
,
25 ShutdownMethod aShutdownMethod
)
26 : mOwningEventTarget(GetCurrentSerialEventTarget()),
27 mThreadPool(new nsThreadPool()),
28 mTaskQueue(TaskQueue::Create(do_AddRef(mThreadPool
), aName
)) {
29 // Configure the threadpool to host a single thread. It will be responsible
30 // for managing the thread's lifetime.
31 MOZ_ALWAYS_SUCCEEDS(mThreadPool
->SetThreadLimit(1));
32 MOZ_ALWAYS_SUCCEEDS(mThreadPool
->SetIdleThreadLimit(1));
33 MOZ_ALWAYS_SUCCEEDS(mThreadPool
->SetIdleThreadTimeout(aIdleTimeoutMS
));
34 MOZ_ALWAYS_SUCCEEDS(mThreadPool
->SetName(nsDependentCString(aName
)));
36 if (aShutdownMethod
== ShutdownMethod::AutomaticShutdown
&&
38 if (nsCOMPtr
<nsIObserverService
> obs
=
39 do_GetService(NS_OBSERVERSERVICE_CONTRACTID
)) {
41 obs
->AddObserver(this, "xpcom-shutdown-threads", false));
46 static void LazyIdleThreadShutdown(nsThreadPool
* aThreadPool
,
47 TaskQueue
* aTaskQueue
) {
48 aTaskQueue
->BeginShutdown();
49 aTaskQueue
->AwaitShutdownAndIdle();
50 aThreadPool
->Shutdown();
53 LazyIdleThread::~LazyIdleThread() {
55 mOwningEventTarget
->Dispatch(NS_NewRunnableFunction(
56 "LazyIdleThread::~LazyIdleThread",
57 [threadPool
= mThreadPool
, taskQueue
= mTaskQueue
] {
58 LazyIdleThreadShutdown(threadPool
, taskQueue
);
63 void LazyIdleThread::Shutdown() {
64 ASSERT_OWNING_THREAD();
68 LazyIdleThreadShutdown(mThreadPool
, mTaskQueue
);
72 nsresult
LazyIdleThread::SetListener(nsIThreadPoolListener
* aListener
) {
73 return mThreadPool
->SetListener(aListener
);
76 NS_IMPL_ISUPPORTS(LazyIdleThread
, nsIEventTarget
, nsISerialEventTarget
,
80 LazyIdleThread::DispatchFromScript(nsIRunnable
* aEvent
, uint32_t aFlags
) {
81 nsCOMPtr
<nsIRunnable
> event(aEvent
);
82 return Dispatch(event
.forget(), aFlags
);
86 LazyIdleThread::Dispatch(already_AddRefed
<nsIRunnable
> aEvent
,
88 return mTaskQueue
->Dispatch(std::move(aEvent
), aFlags
);
92 LazyIdleThread::DelayedDispatch(already_AddRefed
<nsIRunnable
>, uint32_t) {
93 return NS_ERROR_NOT_IMPLEMENTED
;
97 LazyIdleThread::RegisterShutdownTask(nsITargetShutdownTask
* aTask
) {
98 return NS_ERROR_NOT_IMPLEMENTED
;
102 LazyIdleThread::UnregisterShutdownTask(nsITargetShutdownTask
* aTask
) {
103 return NS_ERROR_NOT_IMPLEMENTED
;
107 LazyIdleThread::IsOnCurrentThread(bool* aIsOnCurrentThread
) {
108 return mTaskQueue
->IsOnCurrentThread(aIsOnCurrentThread
);
112 LazyIdleThread::IsOnCurrentThreadInfallible() {
113 return mTaskQueue
->IsOnCurrentThreadInfallible();
117 LazyIdleThread::Observe(nsISupports
* /* aSubject */, const char* aTopic
,
118 const char16_t
* /* aData */) {
119 MOZ_ASSERT(NS_IsMainThread(), "Wrong thread!");
120 MOZ_ASSERT(!strcmp("xpcom-shutdown-threads", aTopic
), "Bad topic!");
126 } // namespace mozilla