My program is deadlocking, and I have no idea why, given that it won't do it when I run it in a debugger, so my first suspect is my rwLock, I wrote my own version because I only wanted to use standard libraries--I don't think a rwLock is included until C++17--and this isn't the sort of thing I normally do.
class RwLock
{
std::mutex mutex;
std::unique_lock<std::mutex> unique_lock;
std::condition_variable condition;
int reading_threads;
bool writing_threads;
public:
RwLock();
~RwLock();
void read_lock();
void read_unlock();
void write_lock();
void write_unlock();
};
RwLock::RwLock() :
mutex(),
unique_lock(mutex, std::defer_lock),
condition(),
reading_threads(0),
writing_threads(false)
{
}
RwLock::~RwLock()
{
//TODO: find something smarter to do here.
write_lock();
}
void RwLock::read_lock()
{
unique_lock.lock();
while(writing_threads)
{
condition.wait(unique_lock);
}
++reading_threads;
unique_lock.unlock();
}
void RwLock::read_unlock()
{
unique_lock.lock();
if(--reading_threads == 0)
{
condition.notify_all();
}
unique_lock.unlock();
}
void RwLock::write_lock()
{
unique_lock.lock();
while(writing_threads)
{
condition.wait(unique_lock);
}
writing_threads = 1;
while(reading_threads)
{
condition.notify_all();
}
unique_lock.unlock();
}
void RwLock::write_unlock()
{
unique_lock.lock();
writing_threads = 0;
condition.notify_all();
unique_lock.unlock();
}
std::shared_timed_mutex
exists prior to C++17: in C++14.
Use it instead, it will have fewer bugs and be faster almost certainly.
C++17 introduces shared_mutex
which can be even faster. But I strongly doubt your ability to implement a faster shared rwlock than shared_timed_mutex
using C++ standard primitives.
Looks good except for two issues in this code:
void RwLock::write_lock()
{
unique_lock.lock();
while(writing_threads)
{
condition.wait(unique_lock);
}
writing_threads = 1;
while(reading_threads)
{
condition.notify_all();
}
unique_lock.unlock();
}
First, you increment writing_threads
too late. A reader could sneak in. It's possible that you don't mind or even want this, but typically this is undesired.
Second, your notify in the last while
loop should be a wait
. Putting it together, we get:
void RwLock::write_lock()
{
unique_lock.lock();
++writing_threads;
while((writing_threads > 1) || (reading_threads > 0))
{
condition.wait(unique_lock);
}
unique_lock.unlock();
}
void RwLock::write_unlock()
{
unique_lock.lock();
--writing_threads; // note change here
condition.notify_all();
unique_lock.unlock();
}
This is actually a bit simpler, which is nice.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.