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 "DelayedRunnable.h"
9 #include "mozilla/ProfilerRunnable.h"
13 DelayedRunnable::DelayedRunnable(already_AddRefed
<nsISerialEventTarget
> aTarget
,
14 already_AddRefed
<nsIRunnable
> aRunnable
,
16 : mozilla::Runnable("DelayedRunnable"),
18 mDelayedFrom(TimeStamp::NowLoRes()),
20 mWrappedRunnable(aRunnable
) {}
22 nsresult
DelayedRunnable::Init() {
23 MutexAutoLock
lock(mMutex
);
24 if (!mWrappedRunnable
) {
25 MOZ_ASSERT_UNREACHABLE();
26 return NS_ERROR_INVALID_ARG
;
29 nsresult rv
= mTarget
->RegisterShutdownTask(this);
31 MOZ_DIAGNOSTIC_ASSERT(
32 rv
== NS_ERROR_UNEXPECTED
,
33 "DelayedRunnable target must support RegisterShutdownTask");
34 NS_WARNING("DelayedRunnable init after target is shutdown");
38 rv
= NS_NewTimerWithCallback(getter_AddRefs(mTimer
), this, mDelay
,
39 nsITimer::TYPE_ONE_SHOT
, mTarget
);
40 if (NS_WARN_IF(NS_FAILED(rv
))) {
41 mTarget
->UnregisterShutdownTask(this);
46 NS_IMETHODIMP
DelayedRunnable::Run() {
47 MOZ_ASSERT(mTarget
->IsOnCurrentThread());
49 nsCOMPtr
<nsIRunnable
> runnable
;
51 MutexAutoLock
lock(mMutex
);
52 MOZ_ASSERT(mTimer
, "Init() must have been called");
55 if (!mWrappedRunnable
) {
60 if ((mozilla::TimeStamp::NowLoRes() - mDelayedFrom
).ToMilliseconds() <
62 return NS_OK
; // Let the nsITimer run us.
66 mTarget
->UnregisterShutdownTask(this);
67 runnable
= mWrappedRunnable
.forget();
70 AUTO_PROFILE_FOLLOWING_RUNNABLE(runnable
);
71 return runnable
->Run();
74 NS_IMETHODIMP
DelayedRunnable::Notify(nsITimer
* aTimer
) {
75 MOZ_ASSERT(mTarget
->IsOnCurrentThread());
77 nsCOMPtr
<nsIRunnable
> runnable
;
79 MutexAutoLock
lock(mMutex
);
80 MOZ_ASSERT(mTimer
, "Init() must have been called");
82 // We may have already run due to races
83 if (!mWrappedRunnable
) {
87 mTarget
->UnregisterShutdownTask(this);
88 runnable
= mWrappedRunnable
.forget();
91 AUTO_PROFILE_FOLLOWING_RUNNABLE(runnable
);
92 return runnable
->Run();
95 void DelayedRunnable::TargetShutdown() {
96 MOZ_ASSERT(mTarget
->IsOnCurrentThread());
99 MutexAutoLock
lock(mMutex
);
100 if (!mWrappedRunnable
) {
103 mWrappedRunnable
= nullptr;
110 NS_IMPL_ISUPPORTS_INHERITED(DelayedRunnable
, Runnable
, nsITimerCallback
,
111 nsITargetShutdownTask
)
113 } // namespace mozilla