/*! * Release the lock. Used for both "readers" and "writers". */ void Unlock() { int prevCount = ATOMIC::OPS::Increment(&_count, -1); if (prevCount == 0) { // If the count goes from 0 => -1, there is a waiting writer and // this is the last reader. Wake up the waiting writer. // _waiterSemaphore.Set(); } else if (prevCount == -1) { // If the count goes from -1 => -2, this is a writer. Reset '_count' // and release the lock, which allows new readers or writers to // acquire it. // _count = 0; _lock.Unlock(); } else { // Any other value indicates either: 1) that this is a reader releasing // the lock and there are other active readers, or 2) that this is the // last reader releasing the lock and there are no waiting writers. // SYNC_CHECK_ASSERT(prevCount > 0); } }
// Set new state to what it would be when the lock is acquired for write access // by a writer from the waiting list. // Return FALSE if write access can not be acquired in the current state. // bool ProposeWriteAfterWaitState() { SYNC_CHECK_ASSERT(_current.WaitingWriters() != 0); if (_current.ActiveReaders() != 0) return false; _next.ActiveReaders() = WRITE_LOCKVAL; _next.WaitingWriters() = _current.WaitingWriters() - 1; return true; }
// Set new state to what it would be when the lock is released. // void ProposeUnlockState() { if (_current.ActiveReaders() == WRITE_LOCKVAL) { _next.ActiveReaders() = 0; //Release write lock } else { SYNC_CHECK_ASSERT(_current.ActiveReaders() != 0); _next.ActiveReaders() = _current.ActiveReaders() - 1; // Release read lock } _next.WaitingWriters() = _current.WaitingWriters(); }
// Set new state to what it would be when one more writer is added to the waiting // list of the current state. // void ProposeWaitState() { _next.ActiveReaders() = _current.ActiveReaders(); _next.WaitingWriters() = _current.WaitingWriters() + 1; SYNC_CHECK_ASSERT(_next.WaitingWriters() != 0); }