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
->SetIdleThreadGraceTimeout(0));
34 MOZ_ALWAYS_SUCCEEDS(mThreadPool
->SetIdleThreadMaximumTimeout(aIdleTimeoutMS
));
35 MOZ_ALWAYS_SUCCEEDS(mThreadPool
->SetName(nsDependentCString(aName
)));
37 if (aShutdownMethod
== ShutdownMethod::AutomaticShutdown
&&
39 if (nsCOMPtr
<nsIObserverService
> obs
=
40 do_GetService(NS_OBSERVERSERVICE_CONTRACTID
)) {
42 obs
->AddObserver(this, "xpcom-shutdown-threads", false));
47 static void LazyIdleThreadShutdown(nsThreadPool
* aThreadPool
,
48 TaskQueue
* aTaskQueue
) {
49 aTaskQueue
->BeginShutdown();
50 aTaskQueue
->AwaitShutdownAndIdle();
51 aThreadPool
->Shutdown();
54 LazyIdleThread::~LazyIdleThread() {
56 mOwningEventTarget
->Dispatch(NS_NewRunnableFunction(
57 "LazyIdleThread::~LazyIdleThread",
58 [threadPool
= mThreadPool
, taskQueue
= mTaskQueue
] {
59 LazyIdleThreadShutdown(threadPool
, taskQueue
);
64 void LazyIdleThread::Shutdown() {
65 ASSERT_OWNING_THREAD();
69 LazyIdleThreadShutdown(mThreadPool
, mTaskQueue
);
73 nsresult
LazyIdleThread::SetListener(nsIThreadPoolListener
* aListener
) {
74 return mThreadPool
->SetListener(aListener
);
77 NS_IMPL_ISUPPORTS(LazyIdleThread
, nsIEventTarget
, nsISerialEventTarget
,
81 LazyIdleThread::DispatchFromScript(nsIRunnable
* aEvent
, uint32_t aFlags
) {
82 nsCOMPtr
<nsIRunnable
> event(aEvent
);
83 return Dispatch(event
.forget(), aFlags
);
87 LazyIdleThread::Dispatch(already_AddRefed
<nsIRunnable
> aEvent
,
89 return mTaskQueue
->Dispatch(std::move(aEvent
), aFlags
);
93 LazyIdleThread::DelayedDispatch(already_AddRefed
<nsIRunnable
>, uint32_t) {
94 return NS_ERROR_NOT_IMPLEMENTED
;
98 LazyIdleThread::RegisterShutdownTask(nsITargetShutdownTask
* aTask
) {
99 return NS_ERROR_NOT_IMPLEMENTED
;
103 LazyIdleThread::UnregisterShutdownTask(nsITargetShutdownTask
* aTask
) {
104 return NS_ERROR_NOT_IMPLEMENTED
;
108 LazyIdleThread::IsOnCurrentThread(bool* aIsOnCurrentThread
) {
109 return mTaskQueue
->IsOnCurrentThread(aIsOnCurrentThread
);
113 LazyIdleThread::IsOnCurrentThreadInfallible() {
114 return mTaskQueue
->IsOnCurrentThreadInfallible();
118 LazyIdleThread::Observe(nsISupports
* /* aSubject */, const char* aTopic
,
119 const char16_t
* /* aData */) {
120 MOZ_ASSERT(NS_IsMainThread(), "Wrong thread!");
121 MOZ_ASSERT(!strcmp("xpcom-shutdown-threads", aTopic
), "Bad topic!");
127 } // namespace mozilla