|
class MyLocker { |
|
// Exclusive Write, which will wait for shared read to finish |
|
// Shared read, which will wait for Exclusive Write to finish |
|
public: |
|
MyLocker() : mSharedUsage(0), mExclusiveWrite(false) {} |
|
void ExclusiveWriteLock(); |
|
void ExclusiveWriteUnLock(); |
|
void SharedReadLock(); |
|
void SharedReadUnLock(); |
|
private: |
|
mutex mMutex; |
|
unsigned int mSharedUsage; ///< Each reader to increase it when reading so Writer will wait |
|
bool mExclusiveWrite; ///< Each writer will wait for other writer to finish |
|
condition_variable TellWriters; ///< Writers wait for other writers |
|
condition_variable TellReaders; ///< Readers wait for Writers to finish, Writers wait for readers to finish |
|
}; |
|
|
|
void MyLocker::ExclusiveWriteLock() { |
|
unique_lock<mutex> guard(mMutex); |
|
if (mExclusiveWrite) { |
|
// Wait for other writers to finish |
|
TellWriters.wait(guard); |
|
} |
|
// I am the sole writer now |
|
mExclusiveWrite = true; |
|
if (mSharedUsage != 0) { |
|
// wait for all readers to finish |
|
TellReaders.wait(guard); |
|
} |
|
// Sole Writer, no readers, Full EXCLUSION |
|
} |
|
|
|
void MyLocker::ExclusiveWriteUnLock() { |
|
{ |
|
// reduced scope to destory the guard as soon as possible |
|
// and before notifying all readers and writers |
|
unique_lock<mutex> guard(mMutex); |
|
mExclusiveWrite = false; |
|
} |
|
// tell all readers and writers to resume operation |
|
TellWriters.notify_all(); |
|
TellReaders.notify_all(); |
|
} |
|
|
|
void MyLocker::SharedReadLock() { |
|
unique_lock<mutex> guard(mMutex); |
|
if (mExclusiveWrite) { |
|
// wait for writers to finish |
|
TellWriters.wait(guard); |
|
} |
|
// I will now be writing |
|
mSharedUsage++; |
|
} |
|
void MyLocker::SharedReadUnLock() { |
|
{ |
|
// reduced scope to destory the guard as soon as possible |
|
// and before notifying all readers and writers |
|
unique_lock<mutex> guard(mMutex); |
|
SharedUsage--; |
|
} |
|
// done reading, tell all to resume |
|
TellWriters.notify_all(); |
|
TellReaders.notify_all(); |
|
} |