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 "ServiceWorkerJobQueue.h"
9 #include "nsThreadUtils.h"
10 #include "ServiceWorkerJob.h"
11 #include "mozilla/dom/WorkerCommon.h"
16 class ServiceWorkerJobQueue::Callback final
17 : public ServiceWorkerJob::Callback
{
18 RefPtr
<ServiceWorkerJobQueue
> mQueue
;
20 ~Callback() = default;
23 explicit Callback(ServiceWorkerJobQueue
* aQueue
) : mQueue(aQueue
) {
24 MOZ_ASSERT(NS_IsMainThread());
28 virtual void JobFinished(ServiceWorkerJob
* aJob
,
29 ErrorResult
& aStatus
) override
{
30 MOZ_ASSERT(NS_IsMainThread());
31 mQueue
->JobFinished(aJob
);
34 virtual void JobDiscarded(ErrorResult
&) override
{
35 // no-op; nothing to do.
38 NS_INLINE_DECL_REFCOUNTING(ServiceWorkerJobQueue::Callback
, override
)
41 ServiceWorkerJobQueue::~ServiceWorkerJobQueue() {
42 MOZ_ASSERT(NS_IsMainThread());
43 MOZ_ASSERT(mJobList
.IsEmpty());
46 void ServiceWorkerJobQueue::JobFinished(ServiceWorkerJob
* aJob
) {
47 MOZ_ASSERT(NS_IsMainThread());
50 // XXX There are some corner cases where jobs can double-complete. Until
51 // we track all these down we do a non-fatal assert in debug builds and
52 // a runtime check to verify the queue is in the correct state.
53 NS_ASSERTION(!mJobList
.IsEmpty(),
54 "Job queue should contain the job that just completed.");
55 NS_ASSERTION(mJobList
.SafeElementAt(0, nullptr) == aJob
,
56 "Job queue should contain the job that just completed.");
57 if (NS_WARN_IF(mJobList
.SafeElementAt(0, nullptr) != aJob
)) {
61 mJobList
.RemoveElementAt(0);
63 if (mJobList
.IsEmpty()) {
70 void ServiceWorkerJobQueue::RunJob() {
71 MOZ_ASSERT(NS_IsMainThread());
72 MOZ_ASSERT(!mJobList
.IsEmpty());
73 MOZ_ASSERT(mJobList
[0]->GetState() == ServiceWorkerJob::State::Initial
);
75 RefPtr
<Callback
> callback
= new Callback(this);
76 mJobList
[0]->Start(callback
);
79 ServiceWorkerJobQueue::ServiceWorkerJobQueue() {
80 MOZ_ASSERT(NS_IsMainThread());
83 void ServiceWorkerJobQueue::ScheduleJob(ServiceWorkerJob
* aJob
) {
84 MOZ_ASSERT(NS_IsMainThread());
86 MOZ_ASSERT(!mJobList
.Contains(aJob
));
88 if (mJobList
.IsEmpty()) {
89 mJobList
.AppendElement(aJob
);
94 MOZ_ASSERT(mJobList
[0]->GetState() == ServiceWorkerJob::State::Started
);
96 RefPtr
<ServiceWorkerJob
>& tailJob
= mJobList
[mJobList
.Length() - 1];
97 if (!tailJob
->ResultCallbacksInvoked() && aJob
->IsEquivalentTo(tailJob
)) {
98 tailJob
->StealResultCallbacksFrom(aJob
);
102 mJobList
.AppendElement(aJob
);
105 void ServiceWorkerJobQueue::CancelAll() {
106 MOZ_ASSERT(NS_IsMainThread());
108 for (RefPtr
<ServiceWorkerJob
>& job
: mJobList
) {
112 // Remove jobs that are queued but not started since they should never
113 // run after being canceled. This means throwing away all jobs except
114 // for the job at the front of the list.
115 if (!mJobList
.IsEmpty()) {
116 MOZ_ASSERT(mJobList
[0]->GetState() == ServiceWorkerJob::State::Started
);
117 mJobList
.TruncateLength(1);
122 } // namespace mozilla