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 #ifndef mozilla_dom_workerinternal_Queue_h
8 #define mozilla_dom_workerinternal_Queue_h
10 #include "mozilla/Mutex.h"
13 namespace mozilla::dom::workerinternals
{
15 template <typename T
, int TCount
>
16 struct StorageWithTArray
{
17 typedef AutoTArray
<T
, TCount
> StorageType
;
19 static void Reverse(StorageType
& aStorage
) {
20 uint32_t length
= aStorage
.Length();
21 for (uint32_t index
= 0; index
< length
/ 2; index
++) {
22 uint32_t reverseIndex
= length
- 1 - index
;
24 T t1
= aStorage
.ElementAt(index
);
25 T t2
= aStorage
.ElementAt(reverseIndex
);
27 aStorage
.ReplaceElementsAt(index
, 1, t2
);
28 aStorage
.ReplaceElementsAt(reverseIndex
, 1, t1
);
32 static bool IsEmpty(const StorageType
& aStorage
) {
33 return !!aStorage
.IsEmpty();
36 static void Push(StorageType
& aStorage
, const T
& aEntry
) {
37 aStorage
.AppendElement(aEntry
);
40 static bool Pop(StorageType
& aStorage
, T
& aEntry
) {
41 if (IsEmpty(aStorage
)) {
45 aEntry
= aStorage
.PopLastElement();
49 static void Clear(StorageType
& aStorage
) { aStorage
.Clear(); }
51 static void Compact(StorageType
& aStorage
) { aStorage
.Compact(); }
54 class MOZ_CAPABILITY("mutex") LockingWithMutex
{
55 mozilla::Mutex mMutex
;
58 LockingWithMutex() : mMutex("LockingWithMutex::mMutex") {}
60 void Lock() MOZ_CAPABILITY_ACQUIRE() { mMutex
.Lock(); }
62 void Unlock() MOZ_CAPABILITY_RELEASE() { mMutex
.Unlock(); }
64 class MOZ_SCOPED_CAPABILITY AutoLock
{
65 LockingWithMutex
& mHost
;
68 explicit AutoLock(LockingWithMutex
& aHost
) MOZ_CAPABILITY_ACQUIRE(aHost
)
73 ~AutoLock() MOZ_CAPABILITY_RELEASE() { mHost
.Unlock(); }
76 friend class AutoLock
;
87 explicit AutoLock(NoLocking
& aHost
) {}
89 ~AutoLock() = default;
93 template <typename T
, int TCount
= 256, class LockingPolicy
= NoLocking
,
95 StorageWithTArray
<T
, TCount
% 2 ? TCount
/ 2 + 1 : TCount
/ 2> >
96 class Queue
: public LockingPolicy
{
97 typedef typename
StoragePolicy::StorageType StorageType
;
98 typedef typename
LockingPolicy::AutoLock AutoLock
;
100 StorageType mStorage1
;
101 StorageType mStorage2
;
107 Queue() : mFront(&mStorage1
), mBack(&mStorage2
) {}
110 AutoLock
lock(*this);
111 return StoragePolicy::IsEmpty(*mFront
) && StoragePolicy::IsEmpty(*mBack
);
114 void Push(const T
& aEntry
) {
115 AutoLock
lock(*this);
116 StoragePolicy::Push(*mBack
, aEntry
);
119 bool Pop(T
& aEntry
) {
120 AutoLock
lock(*this);
121 if (StoragePolicy::IsEmpty(*mFront
)) {
122 StoragePolicy::Compact(*mFront
);
123 StoragePolicy::Reverse(*mBack
);
124 StorageType
* tmp
= mFront
;
128 return StoragePolicy::Pop(*mFront
, aEntry
);
132 AutoLock
lock(*this);
133 StoragePolicy::Clear(*mFront
);
134 StoragePolicy::Clear(*mBack
);
137 // XXX Do we need this?
138 void Lock() { LockingPolicy::Lock(); }
140 // XXX Do we need this?
141 void Unlock() { LockingPolicy::Unlock(); }
144 // Queue is not copyable.
146 Queue
& operator=(const Queue
&);
149 } // namespace mozilla::dom::workerinternals
151 #endif /* mozilla_dom_workerinternals_Queue_h*/