Thu, 22 Jan 2015 13:21:57 +0100
Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6
1 /* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #ifndef mozilla_dom_workers_queue_h__
7 #define mozilla_dom_workers_queue_h__
9 #include "Workers.h"
11 #include "mozilla/Mutex.h"
12 #include "nsTArray.h"
14 BEGIN_WORKERS_NAMESPACE
16 template <typename T, int TCount>
17 struct StorageWithTArray
18 {
19 typedef nsAutoTArray<T, TCount> StorageType;
21 static void Reverse(StorageType& aStorage)
22 {
23 uint32_t length = aStorage.Length();
24 for (uint32_t index = 0; index < length / 2; index++) {
25 uint32_t reverseIndex = length - 1 - index;
27 T t1 = aStorage.ElementAt(index);
28 T t2 = aStorage.ElementAt(reverseIndex);
30 aStorage.ReplaceElementsAt(index, 1, t2);
31 aStorage.ReplaceElementsAt(reverseIndex, 1, t1);
32 }
33 }
35 static bool IsEmpty(const StorageType& aStorage)
36 {
37 return !!aStorage.IsEmpty();
38 }
40 static bool Push(StorageType& aStorage, const T& aEntry)
41 {
42 return !!aStorage.AppendElement(aEntry);
43 }
45 static bool Pop(StorageType& aStorage, T& aEntry)
46 {
47 if (IsEmpty(aStorage)) {
48 return false;
49 }
51 uint32_t index = aStorage.Length() - 1;
52 aEntry = aStorage.ElementAt(index);
53 aStorage.RemoveElementAt(index);
54 return true;
55 }
57 static void Clear(StorageType& aStorage)
58 {
59 aStorage.Clear();
60 }
62 static void Compact(StorageType& aStorage)
63 {
64 aStorage.Compact();
65 }
66 };
68 class LockingWithMutex
69 {
70 mozilla::Mutex mMutex;
72 protected:
73 LockingWithMutex()
74 : mMutex("LockingWithMutex::mMutex")
75 { }
77 void Lock()
78 {
79 mMutex.Lock();
80 }
82 void Unlock()
83 {
84 mMutex.Unlock();
85 }
87 class AutoLock
88 {
89 LockingWithMutex& mHost;
91 public:
92 AutoLock(LockingWithMutex& aHost)
93 : mHost(aHost)
94 {
95 mHost.Lock();
96 }
98 ~AutoLock()
99 {
100 mHost.Unlock();
101 }
102 };
104 friend class AutoLock;
105 };
107 class NoLocking
108 {
109 protected:
110 void Lock()
111 { }
113 void Unlock()
114 { }
116 class AutoLock
117 {
118 public:
119 AutoLock(NoLocking& aHost)
120 { }
122 ~AutoLock()
123 { }
124 };
125 };
127 template <typename T,
128 int TCount = 256,
129 class LockingPolicy = NoLocking,
130 class StoragePolicy = StorageWithTArray<T, TCount % 2 ?
131 TCount / 2 + 1 :
132 TCount / 2> >
133 class Queue : public LockingPolicy
134 {
135 typedef typename StoragePolicy::StorageType StorageType;
136 typedef typename LockingPolicy::AutoLock AutoLock;
138 StorageType mStorage1;
139 StorageType mStorage2;
141 StorageType* mFront;
142 StorageType* mBack;
144 public:
145 Queue()
146 : mFront(&mStorage1), mBack(&mStorage2)
147 { }
149 bool IsEmpty()
150 {
151 AutoLock lock(*this);
152 return StoragePolicy::IsEmpty(*mFront) &&
153 StoragePolicy::IsEmpty(*mBack);
154 }
156 bool Push(const T& aEntry)
157 {
158 AutoLock lock(*this);
159 return StoragePolicy::Push(*mBack, aEntry);
160 }
162 bool Pop(T& aEntry)
163 {
164 AutoLock lock(*this);
165 if (StoragePolicy::IsEmpty(*mFront)) {
166 StoragePolicy::Compact(*mFront);
167 StoragePolicy::Reverse(*mBack);
168 StorageType* tmp = mFront;
169 mFront = mBack;
170 mBack = tmp;
171 }
172 return StoragePolicy::Pop(*mFront, aEntry);
173 }
175 void Clear()
176 {
177 AutoLock lock(*this);
178 StoragePolicy::Clear(*mFront);
179 StoragePolicy::Clear(*mBack);
180 }
182 // XXX Do we need this?
183 void Lock()
184 {
185 LockingPolicy::Lock();
186 }
188 // XXX Do we need this?
189 void Unlock()
190 {
191 LockingPolicy::Unlock();
192 }
194 private:
195 // Queue is not copyable.
196 Queue(const Queue&);
197 Queue & operator=(const Queue&);
198 };
200 END_WORKERS_NAMESPACE
202 #endif /* mozilla_dom_workers_queue_h__ */