diff options
Diffstat (limited to '')
-rw-r--r-- | linden/indra/llcommon/llthread.h | 96 |
1 files changed, 95 insertions, 1 deletions
diff --git a/linden/indra/llcommon/llthread.h b/linden/indra/llcommon/llthread.h index 8708929..1e982cc 100644 --- a/linden/indra/llcommon/llthread.h +++ b/linden/indra/llcommon/llthread.h | |||
@@ -235,6 +235,101 @@ private: | |||
235 | LLMutexBase* mMutex; | 235 | LLMutexBase* mMutex; |
236 | }; | 236 | }; |
237 | 237 | ||
238 | class AIRWLock | ||
239 | { | ||
240 | public: | ||
241 | AIRWLock(AIAPRPool& parent = LLThread::tldata().mRootPool) : | ||
242 | mWriterWaitingMutex(parent), mNoHoldersCondition(parent), mHoldersCount(0), mWriterIsWaiting(false) { } | ||
243 | |||
244 | private: | ||
245 | LLMutex mWriterWaitingMutex; //!< This mutex is locked while some writer is waiting for access. | ||
246 | LLCondition mNoHoldersCondition; //!< Access control for mHoldersCount. Condition true when there are no more holders. | ||
247 | int mHoldersCount; //!< Number of readers or -1 if a writer locked this object. | ||
248 | // This is volatile because we read it outside the critical area of mWriterWaitingMutex, at [1]. | ||
249 | // That means that other threads can change it while we are already in the (inlined) function rdlock. | ||
250 | // Without volatile, the following assembly would fail: | ||
251 | // register x = mWriterIsWaiting; | ||
252 | // /* some thread changes mWriterIsWaiting */ | ||
253 | // if (x ... | ||
254 | // However, because the function is fuzzy to begin with (we don't mind that this race | ||
255 | // condition exists) it would work fine without volatile. So, basically it's just here | ||
256 | // out of principle ;). -- Aleric | ||
257 | bool volatile mWriterIsWaiting; //!< True when there is a writer waiting for write access. | ||
258 | |||
259 | public: | ||
260 | void rdlock(bool high_priority = false) | ||
261 | { | ||
262 | // Give a writer a higher priority (kinda fuzzy). | ||
263 | if (mWriterIsWaiting && !high_priority) // [1] If there is a writer interested, | ||
264 | { | ||
265 | mWriterWaitingMutex.lock(); // [2] then give it precedence and wait here. | ||
266 | // If we get here then the writer got it's access; mHoldersCount == -1. | ||
267 | mWriterWaitingMutex.unlock(); | ||
268 | } | ||
269 | mNoHoldersCondition.lock(); // [3] Get exclusive access to mHoldersCount. | ||
270 | while (mHoldersCount == -1) // [4] | ||
271 | { | ||
272 | mNoHoldersCondition.wait(); // [5] Wait till mHoldersCount is (or just was) 0. | ||
273 | } | ||
274 | ++mHoldersCount; // One more reader. | ||
275 | mNoHoldersCondition.unlock(); // Release lock on mHoldersCount. | ||
276 | } | ||
277 | void rdunlock(void) | ||
278 | { | ||
279 | mNoHoldersCondition.lock(); // Get exclusive access to mHoldersCount. | ||
280 | if (--mHoldersCount == 0) // Was this the last reader? | ||
281 | { | ||
282 | mNoHoldersCondition.signal(); // Tell waiting threads, see [5], [6] and [7]. | ||
283 | } | ||
284 | mNoHoldersCondition.unlock(); // Release lock on mHoldersCount. | ||
285 | } | ||
286 | void wrlock(void) | ||
287 | { | ||
288 | mWriterWaitingMutex.lock(); // Block new readers, see [2], | ||
289 | mWriterIsWaiting = true; // from this moment on, see [1]. | ||
290 | mNoHoldersCondition.lock(); // Get exclusive access to mHoldersCount. | ||
291 | while (mHoldersCount != 0) // Other readers or writers have this lock? | ||
292 | { | ||
293 | mNoHoldersCondition.wait(); // [6] Wait till mHoldersCount is (or just was) 0. | ||
294 | } | ||
295 | mWriterIsWaiting = false; // Stop checking the lock for new readers, see [1]. | ||
296 | mWriterWaitingMutex.unlock(); // Release blocked readers, they will still hang at [3]. | ||
297 | mHoldersCount = -1; // We are a writer now (will cause a hang at [5], see [4]). | ||
298 | mNoHoldersCondition.unlock(); // Release lock on mHolders (readers go from [3] to [5]). | ||
299 | } | ||
300 | void wrunlock(void) | ||
301 | { | ||
302 | mNoHoldersCondition.lock(); // Get exclusive access to mHoldersCount. | ||
303 | mHoldersCount = 0; // We have no writer anymore. | ||
304 | mNoHoldersCondition.signal(); // Tell waiting threads, see [5], [6] and [7]. | ||
305 | mNoHoldersCondition.unlock(); // Release lock on mHoldersCount. | ||
306 | } | ||
307 | void rd2wrlock(void) | ||
308 | { | ||
309 | mNoHoldersCondition.lock(); // Get exclusive access to mHoldersCount. Blocks new readers at [3]. | ||
310 | if (--mHoldersCount > 0) // Any other reads left? | ||
311 | { | ||
312 | mWriterWaitingMutex.lock(); // Block new readers, see [2], | ||
313 | mWriterIsWaiting = true; // from this moment on, see [1]. | ||
314 | while (mHoldersCount != 0) // Other readers (still) have this lock? | ||
315 | { | ||
316 | mNoHoldersCondition.wait(); // [7] Wait till mHoldersCount is (or just was) 0. | ||
317 | } | ||
318 | mWriterIsWaiting = false; // Stop checking the lock for new readers, see [1]. | ||
319 | mWriterWaitingMutex.unlock(); // Release blocked readers, they will still hang at [3]. | ||
320 | } | ||
321 | mHoldersCount = -1; // We are a writer now (will cause a hang at [5], see [4]). | ||
322 | mNoHoldersCondition.unlock(); // Release lock on mHolders (readers go from [3] to [5]). | ||
323 | } | ||
324 | void wr2rdlock(void) | ||
325 | { | ||
326 | mNoHoldersCondition.lock(); // Get exclusive access to mHoldersCount. | ||
327 | mHoldersCount = 1; // Turn writer into a reader. | ||
328 | mNoHoldersCondition.signal(); // Tell waiting readers, see [5]. | ||
329 | mNoHoldersCondition.unlock(); // Release lock on mHoldersCount. | ||
330 | } | ||
331 | }; | ||
332 | |||
238 | //============================================================================ | 333 | //============================================================================ |
239 | 334 | ||
240 | void LLThread::lockData() | 335 | void LLThread::lockData() |
@@ -247,7 +342,6 @@ void LLThread::unlockData() | |||
247 | mRunCondition->unlock(); | 342 | mRunCondition->unlock(); |
248 | } | 343 | } |
249 | 344 | ||
250 | |||
251 | //============================================================================ | 345 | //============================================================================ |
252 | 346 | ||
253 | // see llmemory.h for LLPointer<> definition | 347 | // see llmemory.h for LLPointer<> definition |