1 |
// Truck Computer Dooom! |
2 |
// |
3 |
// Douglas Thrift |
4 |
// |
5 |
// $Id$ |
6 |
|
7 |
/* Menes - C++ High-Level Utility Library |
8 |
* Copyright (C) 2003-2005 Jay Freeman (saurik) |
9 |
*/ |
10 |
|
11 |
/* |
12 |
* Redistribution and use in source and binary |
13 |
* forms, with or without modification, are permitted |
14 |
* provided that the following conditions are met: |
15 |
* |
16 |
* 1. Redistributions of source code must retain the |
17 |
* above copyright notice, this list of conditions |
18 |
* and the following disclaimer. |
19 |
* 2. Redistributions in binary form must reproduce the |
20 |
* above copyright notice, this list of conditions |
21 |
* and the following disclaimer in the documentation |
22 |
* and/or other materials provided with the |
23 |
* distribution. |
24 |
* 3. The name of the author may not be used to endorse |
25 |
* or promote products derived from this software |
26 |
* without specific prior written permission. |
27 |
* |
28 |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' |
29 |
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, |
30 |
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
31 |
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
32 |
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE |
33 |
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
34 |
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
35 |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
36 |
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
37 |
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
38 |
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR |
39 |
* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN |
40 |
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF |
41 |
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
42 |
*/ |
43 |
|
44 |
#ifndef _scopes_hpp_ |
45 |
#define _scopes_hpp_ |
46 |
|
47 |
#include <foreach.hpp> |
48 |
|
49 |
#include <algorithm> |
50 |
#include <vector> |
51 |
|
52 |
namespace be { |
53 |
struct Destruct { |
54 |
virtual ~Destruct() { |
55 |
} |
56 |
}; |
57 |
|
58 |
// XXX: this should support allocator templates |
59 |
template <typename Type_> |
60 |
struct DestructImpl : |
61 |
public Destruct |
62 |
{ |
63 |
private: |
64 |
Type_ *object_; |
65 |
|
66 |
public: |
67 |
DestructImpl(Type_ *object) : |
68 |
object_(object) |
69 |
{ |
70 |
} |
71 |
|
72 |
~DestructImpl() { |
73 |
delete object_; |
74 |
} |
75 |
}; |
76 |
} |
77 |
|
78 |
class Scope { |
79 |
public: |
80 |
inline operator bool() const { |
81 |
return false; |
82 |
} |
83 |
}; |
84 |
|
85 |
// XXX: this should be generalized as it sounds too specific to even be useful |
86 |
class ScopeDestruct { |
87 |
private: |
88 |
typedef std::vector<be::Destruct *> DestructList_; |
89 |
DestructList_ destructs_; |
90 |
|
91 |
public: |
92 |
template <typename Type_> |
93 |
void Insert(Type_ *object) { |
94 |
destructs_.push_back(static_cast<be::Destruct *>(new be::DestructImpl<Type_>(object))); |
95 |
} |
96 |
|
97 |
~ScopeDestruct() { |
98 |
_foreach (std::vector<be::Destruct *>, destruct, destructs_) |
99 |
delete *destruct; |
100 |
} |
101 |
}; |
102 |
|
103 |
template <typename Type_, typename Temp_ = Type_> |
104 |
class ScopeIncrement { |
105 |
private: |
106 |
Temp_ rhs_; |
107 |
Type_ &lhs_; |
108 |
bool keep_; |
109 |
|
110 |
public: |
111 |
inline ScopeIncrement(Type_ &lhs) : |
112 |
rhs_(lhs), |
113 |
lhs_(lhs), |
114 |
keep_(false) |
115 |
{ |
116 |
++lhs; |
117 |
} |
118 |
|
119 |
inline ~ScopeIncrement() { |
120 |
if (!keep_) |
121 |
--lhs_; |
122 |
} |
123 |
|
124 |
inline void Keep() { |
125 |
keep_ = true; |
126 |
} |
127 |
|
128 |
operator const Temp_ &() const { |
129 |
return rhs_; |
130 |
} |
131 |
}; |
132 |
|
133 |
template <typename Type_, typename Temp_ = Type_> |
134 |
class ScopeSet { |
135 |
private: |
136 |
Temp_ rhs_; |
137 |
Type_ &lhs_; |
138 |
bool keep_; |
139 |
|
140 |
public: |
141 |
inline ScopeSet(Type_ &lhs, const Temp_ &rhs) : |
142 |
rhs_(lhs), |
143 |
lhs_(lhs), |
144 |
keep_(false) |
145 |
{ |
146 |
lhs = rhs; |
147 |
} |
148 |
|
149 |
inline ~ScopeSet() { |
150 |
if (!keep_) |
151 |
lhs_ = rhs_; |
152 |
} |
153 |
|
154 |
inline const Temp_ &GetValue() const { |
155 |
return rhs_; |
156 |
} |
157 |
|
158 |
inline void Keep() { |
159 |
keep_ = true; |
160 |
} |
161 |
|
162 |
operator const Temp_ &() const { |
163 |
return GetValue(); |
164 |
} |
165 |
}; |
166 |
|
167 |
template <typename Type_> |
168 |
class ScopeSwap { |
169 |
private: |
170 |
Type_ &lhs_; |
171 |
Type_ &rhs_; |
172 |
|
173 |
public: |
174 |
inline ScopeSwap(Type_ &lhs, Type_ &rhs) : |
175 |
lhs_(lhs), rhs_(rhs) |
176 |
{ |
177 |
std::swap(lhs_, rhs_); |
178 |
} |
179 |
|
180 |
inline ~ScopeSwap() { |
181 |
std::swap(lhs_, rhs_); |
182 |
} |
183 |
}; |
184 |
|
185 |
// XXX: move this out into the world somewhere |
186 |
class FreeLock { |
187 |
public: |
188 |
inline static void Lock() { |
189 |
} |
190 |
|
191 |
inline static void Unlock() { |
192 |
} |
193 |
}; |
194 |
|
195 |
template <typename Lock_> |
196 |
class ScopeLock : |
197 |
public Scope |
198 |
{ |
199 |
protected: |
200 |
Lock_ *lock_; |
201 |
|
202 |
public: |
203 |
explicit ScopeLock(Lock_ &lock) : |
204 |
lock_(&lock) |
205 |
{ |
206 |
lock_->Lock(); |
207 |
} |
208 |
|
209 |
ScopeLock(Lock_ &lock, bool locked) { |
210 |
if (!locked) |
211 |
lock_ = NULL; |
212 |
else { |
213 |
lock_ = &lock; |
214 |
lock_->Lock(); |
215 |
} |
216 |
} |
217 |
|
218 |
~ScopeLock() { |
219 |
Release(); |
220 |
} |
221 |
|
222 |
void Release() { |
223 |
if (lock_ != NULL) { |
224 |
lock_->Unlock(); |
225 |
lock_ = NULL; |
226 |
} |
227 |
} |
228 |
}; |
229 |
|
230 |
namespace be { |
231 |
template <typename Lock_> |
232 |
inline ScopeLock<Lock_> ScopeLock_(Lock_ &lock) { |
233 |
return ScopeLock<Lock_>(lock); |
234 |
} } |
235 |
|
236 |
#define _synchronized(lock) if (const Scope &_scope __attribute__((unused)) = be::ScopeLock_(lock)); else |
237 |
|
238 |
template <typename Lock_> |
239 |
class ScopeUnlock : |
240 |
public Scope |
241 |
{ |
242 |
protected: |
243 |
Lock_ *lock_; |
244 |
bool unlocked_; |
245 |
|
246 |
public: |
247 |
explicit ScopeUnlock(Lock_ &lock) : |
248 |
lock_(&lock) |
249 |
{ |
250 |
lock_->Unlock(); |
251 |
} |
252 |
|
253 |
ScopeUnlock(Lock_ &lock, bool unlocked) { |
254 |
if (!unlocked) |
255 |
lock_ = NULL; |
256 |
else { |
257 |
lock_ = &lock; |
258 |
lock_->Unlock(); |
259 |
} |
260 |
} |
261 |
|
262 |
~ScopeUnlock() { |
263 |
Release(); |
264 |
} |
265 |
|
266 |
void Release() { |
267 |
if (lock_ != NULL) { |
268 |
lock_->Lock(); |
269 |
lock_ = NULL; |
270 |
} |
271 |
} |
272 |
}; |
273 |
|
274 |
namespace be { |
275 |
template <typename Lock_> |
276 |
inline ScopeUnlock<Lock_> ScopeUnlock_(Lock_ &lock) { |
277 |
return ScopeUnlock<Lock_>(lock); |
278 |
} } |
279 |
|
280 |
#define _desynchronized(lock) if (const Scope &_scope __attribute__((unused)) = be::ScopeUnlock_(lock)); else |
281 |
|
282 |
template <typename Lock_> |
283 |
class ScopeReadLock : |
284 |
public Scope |
285 |
{ |
286 |
private: |
287 |
Lock_ &lock_; |
288 |
|
289 |
public: |
290 |
ScopeReadLock(Lock_ &lock) : |
291 |
lock_(lock) |
292 |
{ |
293 |
lock_.ReadLock(); |
294 |
} |
295 |
|
296 |
~ScopeReadLock() { |
297 |
lock_.ReadUnlock(); |
298 |
} |
299 |
}; |
300 |
|
301 |
template <typename Lock_> |
302 |
class ScopeWriteLock : |
303 |
public Scope |
304 |
{ |
305 |
private: |
306 |
Lock_ &lock_; |
307 |
|
308 |
public: |
309 |
ScopeWriteLock(Lock_ &lock) : |
310 |
lock_(lock) |
311 |
{ |
312 |
lock_.WriteLock(); |
313 |
} |
314 |
|
315 |
~ScopeWriteLock() { |
316 |
lock_.WriteUnlock(); |
317 |
} |
318 |
}; |
319 |
|
320 |
#endif//_scopes_hpp_ |