Использование стандартных предварительно протестированных, предварительно собранных вещей всегда хорошо (например, Boost, как предложил другой ответ), но это то, что не так уж сложно построить самостоятельно. Вот маленькая глупая реализация, извлеченная из моего проекта:
#include <pthread.h>
struct rwlock {
pthread_mutex_t lock;
pthread_cond_t read, write;
unsigned readers, writers, read_waiters, write_waiters;
};
void reader_lock(struct rwlock *self) {
pthread_mutex_lock(&self->lock);
if (self->writers || self->write_waiters) {
self->read_waiters++;
do pthread_cond_wait(&self->read, &self->lock);
while (self->writers || self->write_waiters);
self->read_waiters--;
}
self->readers++;
pthread_mutex_unlock(&self->lock);
}
void reader_unlock(struct rwlock *self) {
pthread_mutex_lock(&self->lock);
self->readers--;
if (self->write_waiters)
pthread_cond_signal(&self->write);
pthread_mutex_unlock(&self->lock);
}
void writer_lock(struct rwlock *self) {
pthread_mutex_lock(&self->lock);
if (self->readers || self->writers) {
self->write_waiters++;
do pthread_cond_wait(&self->write, &self->lock);
while (self->readers || self->writers);
self->write_waiters--;
}
self->writers = 1;
pthread_mutex_unlock(&self->lock);
}
void writer_unlock(struct rwlock *self) {
pthread_mutex_lock(&self->lock);
self->writers = 0;
if (self->write_waiters)
pthread_cond_signal(&self->write);
else if (self->read_waiters)
pthread_cond_broadcast(&self->read);
pthread_mutex_unlock(&self->lock);
}
void rwlock_init(struct rwlock *self) {
self->readers = self->writers = self->read_waiters = self->write_waiters = 0;
pthread_mutex_init(&self->lock, NULL);
pthread_cond_init(&self->read, NULL);
pthread_cond_init(&self->write, NULL);
}
pthreads
на самом деле не родной для Windows, но общая идея здесь. Эта реализация слегка пристрастна к писателям (орда писателей может голодать читателей бесконечно); просто измените writer_unlock
, если хотите, чтобы баланс был наоборот.
Да, это C, а не C ++. Перевод - это упражнение, оставленное читателю.
Редактировать
Грег Роджерс указал, что стандарт POSIX указывает pthread_rwlock_*
. Это не поможет, если у вас нет pthreads
, но это заставило меня вспомнить: Pthreads-w32 должно работать! Вместо того, чтобы переносить этот код на non-pthreads
для собственного использования, просто используйте Pthreads-w32 в Windows и родной pthreads
везде.