Bug 1861467 - [wpt-sync] Update web-platform-tests to eedf737ce39c512d0ca3471f988972e...
[gecko.git] / dom / workers / Queue.h
blobcf6593269838715fdf63400f00e99d57b2b5d776
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"
11 #include "nsTArray.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)) {
42 return false;
45 aEntry = aStorage.PopLastElement();
46 return true;
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;
57 protected:
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;
67 public:
68 explicit AutoLock(LockingWithMutex& aHost) MOZ_CAPABILITY_ACQUIRE(aHost)
69 : mHost(aHost) {
70 mHost.Lock();
73 ~AutoLock() MOZ_CAPABILITY_RELEASE() { mHost.Unlock(); }
76 friend class AutoLock;
79 class NoLocking {
80 protected:
81 void Lock() {}
83 void Unlock() {}
85 class AutoLock {
86 public:
87 explicit AutoLock(NoLocking& aHost) {}
89 ~AutoLock() = default;
93 template <typename T, int TCount = 256, class LockingPolicy = NoLocking,
94 class StoragePolicy =
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;
103 StorageType* mFront;
104 StorageType* mBack;
106 public:
107 Queue() : mFront(&mStorage1), mBack(&mStorage2) {}
109 bool IsEmpty() {
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;
125 mFront = mBack;
126 mBack = tmp;
128 return StoragePolicy::Pop(*mFront, aEntry);
131 void Clear() {
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(); }
143 private:
144 // Queue is not copyable.
145 Queue(const Queue&);
146 Queue& operator=(const Queue&);
149 } // namespace mozilla::dom::workerinternals
151 #endif /* mozilla_dom_workerinternals_Queue_h*/