I am currently implementing a read/write lock using boost library, without using shared_lock and unique_lock. I have already read some related questions (e.g., How would a readers/writer lock be implemented in C++11?), but I still want to optimize the implementation.
Here is my code:
enum LockType { NO_LOCK, READ_LOCK, WRITE_LOCK, INC_LOCK };
boost::mutex mutex_;
boost::condition condition_;
LockType lock_;
size_t owner_count_;
void AcquireReadLock() {
mutex_.lock();
while (lock_ != NO_LOCK && lock_ != READ_LOCK){
condition_.wait(mutex_);
}
// if there is no lock, then acquire read lock.
if (lock_ == NO_LOCK) {
lock_ = READ_LOCK;
++owner_count_;
mutex_.unlock();
return;
}
else {
// if there is read lock, then still acquire read lock.
assert(lock_ == READ_LOCK);
++owner_count_;
mutex_.unlock();
return;
}
}
void AcquireWriteLock() {
mutex_.lock();
while (lock_ != NO_LOCK){
condition_.wait(mutex_);
}
// if there is no lock, then acquire write lock.
assert(lock_ == NO_LOCK);
lock_ = WRITE_LOCK;
mutex_.unlock();
return;
}
void ReleaseReadLock() {
mutex_.lock();
--owner_count_;
if (owner_count_ == 0) {
lock_ = NO_LOCK;
}
mutex_.unlock();
// is it correct to use notify_all?
condition_.notify_all();
}
void ReleaseWriteLock() {
mutex_.lock();
lock_ = NO_LOCK;
mutex_.unlock();
// is it correct to use notify_all?
condition_.notify_all();
}
The problem is:
whether I should use notify_all when releasing the lock? According to the document, once a thread gets notified, it will reacquire the lock. If using notify_all, then multiple threads can reacquire the same lock. What will happen then? And whether will a thread acquire the lock before checking the condition (i.e., lock_!=NO_LOCK && lock_!=READ_LOCK)?
how can I optimize the program? obviously, when releasing a read lock, we only need to notify the threads that attempt to acquire the write lock, since read never blocks read. So how to implement this idea?
Thanks in advance for your kind help!