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"
15 namespace workerinternals
{
17 template <typename T
, int TCount
>
18 struct StorageWithTArray
{
19 typedef AutoTArray
<T
, TCount
> StorageType
;
21 static void Reverse(StorageType
& aStorage
) {
22 uint32_t length
= aStorage
.Length();
23 for (uint32_t index
= 0; index
< length
/ 2; index
++) {
24 uint32_t reverseIndex
= length
- 1 - index
;
26 T t1
= aStorage
.ElementAt(index
);
27 T t2
= aStorage
.ElementAt(reverseIndex
);
29 aStorage
.ReplaceElementsAt(index
, 1, t2
);
30 aStorage
.ReplaceElementsAt(reverseIndex
, 1, t1
);
34 static bool IsEmpty(const StorageType
& aStorage
) {
35 return !!aStorage
.IsEmpty();
38 static void Push(StorageType
& aStorage
, const T
& aEntry
) {
39 aStorage
.AppendElement(aEntry
);
42 static bool Pop(StorageType
& aStorage
, T
& aEntry
) {
43 if (IsEmpty(aStorage
)) {
47 aEntry
= aStorage
.PopLastElement();
51 static void Clear(StorageType
& aStorage
) { aStorage
.Clear(); }
53 static void Compact(StorageType
& aStorage
) { aStorage
.Compact(); }
56 class LockingWithMutex
{
57 mozilla::Mutex mMutex
;
60 LockingWithMutex() : mMutex("LockingWithMutex::mMutex") {}
62 void Lock() { mMutex
.Lock(); }
64 void Unlock() { mMutex
.Unlock(); }
67 LockingWithMutex
& mHost
;
70 explicit AutoLock(LockingWithMutex
& aHost
) : mHost(aHost
) { mHost
.Lock(); }
72 ~AutoLock() { mHost
.Unlock(); }
75 friend class AutoLock
;
86 explicit AutoLock(NoLocking
& aHost
) {}
88 ~AutoLock() = default;
92 template <typename T
, int TCount
= 256, class LockingPolicy
= NoLocking
,
94 StorageWithTArray
<T
, TCount
% 2 ? TCount
/ 2 + 1 : TCount
/ 2> >
95 class Queue
: public LockingPolicy
{
96 typedef typename
StoragePolicy::StorageType StorageType
;
97 typedef typename
LockingPolicy::AutoLock AutoLock
;
99 StorageType mStorage1
;
100 StorageType mStorage2
;
106 Queue() : mFront(&mStorage1
), mBack(&mStorage2
) {}
109 AutoLock
lock(*this);
110 return StoragePolicy::IsEmpty(*mFront
) && StoragePolicy::IsEmpty(*mBack
);
113 void Push(const T
& aEntry
) {
114 AutoLock
lock(*this);
115 StoragePolicy::Push(*mBack
, aEntry
);
118 bool Pop(T
& aEntry
) {
119 AutoLock
lock(*this);
120 if (StoragePolicy::IsEmpty(*mFront
)) {
121 StoragePolicy::Compact(*mFront
);
122 StoragePolicy::Reverse(*mBack
);
123 StorageType
* tmp
= mFront
;
127 return StoragePolicy::Pop(*mFront
, aEntry
);
131 AutoLock
lock(*this);
132 StoragePolicy::Clear(*mFront
);
133 StoragePolicy::Clear(*mBack
);
136 // XXX Do we need this?
137 void Lock() { LockingPolicy::Lock(); }
139 // XXX Do we need this?
140 void Unlock() { LockingPolicy::Unlock(); }
143 // Queue is not copyable.
145 Queue
& operator=(const Queue
&);
148 } // namespace workerinternals
150 } // namespace mozilla
152 #endif /* mozilla_dom_workerinternals_Queue_h*/