1 : /* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
2 : /* ***** BEGIN LICENSE BLOCK *****
3 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 : *
5 : * The contents of this file are subject to the Mozilla Public License Version
6 : * 1.1 (the "License"); you may not use this file except in compliance with
7 : * the License. You may obtain a copy of the License at
8 : * http://www.mozilla.org/MPL/
9 : *
10 : * Software distributed under the License is distributed on an "AS IS" basis,
11 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 : * for the specific language governing rights and limitations under the
13 : * License.
14 : *
15 : * The Original Code is Web Workers.
16 : *
17 : * The Initial Developer of the Original Code is
18 : * The Mozilla Foundation.
19 : * Portions created by the Initial Developer are Copyright (C) 2011
20 : * the Initial Developer. All Rights Reserved.
21 : *
22 : * Contributor(s):
23 : * Ben Turner <bent.mozilla@gmail.com> (Original Author)
24 : *
25 : * Alternatively, the contents of this file may be used under the terms of
26 : * either the GNU General Public License Version 2 or later (the "GPL"), or
27 : * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28 : * in which case the provisions of the GPL or the LGPL are applicable instead
29 : * of those above. If you wish to allow use of your version of this file only
30 : * under the terms of either the GPL or the LGPL, and not to allow others to
31 : * use your version of this file under the terms of the MPL, indicate your
32 : * decision by deleting the provisions above and replace them with the notice
33 : * and other provisions required by the GPL or the LGPL. If you do not delete
34 : * the provisions above, a recipient may use your version of this file under
35 : * the terms of any one of the MPL, the GPL or the LGPL.
36 : *
37 : * ***** END LICENSE BLOCK ***** */
38 :
39 : #ifndef mozilla_dom_workers_queue_h__
40 : #define mozilla_dom_workers_queue_h__
41 :
42 : #include "Workers.h"
43 :
44 : #include "mozilla/Mutex.h"
45 : #include "nsTArray.h"
46 :
47 : BEGIN_WORKERS_NAMESPACE
48 :
49 : template <typename T, int TCount>
50 : struct StorageWithTArray
51 : {
52 : typedef nsAutoTArray<T, TCount> StorageType;
53 :
54 0 : static void Reverse(StorageType& aStorage)
55 : {
56 0 : PRUint32 length = aStorage.Length();
57 0 : for (PRUint32 index = 0; index < length / 2; index++) {
58 0 : PRUint32 reverseIndex = length - 1 - index;
59 :
60 0 : T t1 = aStorage.ElementAt(index);
61 0 : T t2 = aStorage.ElementAt(reverseIndex);
62 :
63 0 : aStorage.ReplaceElementsAt(index, 1, t2);
64 0 : aStorage.ReplaceElementsAt(reverseIndex, 1, t1);
65 : }
66 0 : }
67 :
68 0 : static bool IsEmpty(const StorageType& aStorage)
69 : {
70 0 : return !!aStorage.IsEmpty();
71 : }
72 :
73 0 : static bool Push(StorageType& aStorage, const T& aEntry)
74 : {
75 0 : return !!aStorage.AppendElement(aEntry);
76 : }
77 :
78 0 : static bool Pop(StorageType& aStorage, T& aEntry)
79 : {
80 0 : if (IsEmpty(aStorage)) {
81 0 : return false;
82 : }
83 :
84 0 : PRUint32 index = aStorage.Length() - 1;
85 0 : aEntry = aStorage.ElementAt(index);
86 0 : aStorage.RemoveElementAt(index);
87 0 : return true;
88 : }
89 :
90 : static void Clear(StorageType& aStorage)
91 : {
92 : aStorage.Clear();
93 : }
94 :
95 0 : static void Compact(StorageType& aStorage)
96 : {
97 0 : aStorage.Compact();
98 0 : }
99 : };
100 :
101 : class LockingWithMutex
102 : {
103 : mozilla::Mutex mMutex;
104 :
105 : protected:
106 : LockingWithMutex()
107 : : mMutex("LockingWithMutex::mMutex")
108 : { }
109 :
110 : void Lock()
111 : {
112 : mMutex.Lock();
113 : }
114 :
115 : void Unlock()
116 : {
117 : mMutex.Unlock();
118 : }
119 :
120 : class AutoLock
121 : {
122 : LockingWithMutex& mHost;
123 :
124 : public:
125 : AutoLock(LockingWithMutex& aHost)
126 : : mHost(aHost)
127 : {
128 : mHost.Lock();
129 : }
130 :
131 : ~AutoLock()
132 : {
133 : mHost.Unlock();
134 : }
135 : };
136 :
137 : friend class AutoLock;
138 : };
139 :
140 : class NoLocking
141 0 : {
142 : protected:
143 : void Lock()
144 : { }
145 :
146 : void Unlock()
147 : { }
148 :
149 : class AutoLock
150 : {
151 : public:
152 0 : AutoLock(NoLocking& aHost)
153 0 : { }
154 :
155 0 : ~AutoLock()
156 0 : { }
157 : };
158 : };
159 :
160 : template <typename T,
161 : int TCount = 256,
162 : class LockingPolicy = NoLocking,
163 : class StoragePolicy = StorageWithTArray<T, TCount % 2 ?
164 : TCount / 2 + 1 :
165 : TCount / 2> >
166 : class Queue : public LockingPolicy
167 0 : {
168 : typedef typename StoragePolicy::StorageType StorageType;
169 : typedef typename LockingPolicy::AutoLock AutoLock;
170 :
171 : StorageType mStorage1;
172 : StorageType mStorage2;
173 :
174 : StorageType* mFront;
175 : StorageType* mBack;
176 :
177 : public:
178 0 : Queue()
179 0 : : mFront(&mStorage1), mBack(&mStorage2)
180 0 : { }
181 :
182 0 : bool IsEmpty()
183 : {
184 0 : AutoLock lock(*this);
185 : return StoragePolicy::IsEmpty(*mFront) &&
186 0 : StoragePolicy::IsEmpty(*mBack);
187 : }
188 :
189 0 : bool Push(const T& aEntry)
190 : {
191 0 : AutoLock lock(*this);
192 0 : return StoragePolicy::Push(*mBack, aEntry);
193 : }
194 :
195 0 : bool Pop(T& aEntry)
196 : {
197 0 : AutoLock lock(*this);
198 0 : if (StoragePolicy::IsEmpty(*mFront)) {
199 0 : StoragePolicy::Compact(*mFront);
200 0 : StoragePolicy::Reverse(*mBack);
201 0 : StorageType* tmp = mFront;
202 0 : mFront = mBack;
203 0 : mBack = tmp;
204 : }
205 0 : return StoragePolicy::Pop(*mFront, aEntry);
206 : }
207 :
208 : void Clear()
209 : {
210 : AutoLock lock(*this);
211 : StoragePolicy::Clear(*mFront);
212 : StoragePolicy::Clear(*mBack);
213 : }
214 :
215 : // XXX Do we need this?
216 : void Lock()
217 : {
218 : LockingPolicy::Lock();
219 : }
220 :
221 : // XXX Do we need this?
222 : void Unlock()
223 : {
224 : LockingPolicy::Unlock();
225 : }
226 :
227 : private:
228 : // Queue is not copyable.
229 : Queue(const Queue&);
230 : Queue & operator=(const Queue&);
231 : };
232 :
233 : END_WORKERS_NAMESPACE
234 :
235 : #endif /* mozilla_dom_workers_queue_h__ */
|