读写锁
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#include <list>
bool quitting = false;
int data = 0;
pthread_rwlock_t rwlock = PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP;
class Reader {
int id_;
pthread_t thread_;
public:
explicit Reader(int id)
id_(id)
{
pthread_create(&thread_, nullptr, &Reader::_run, this);
}
~Reader() {
pthread_join(thread_, nullptr);
}
void run() {
while (!quitting) {
pthread_rwlock_rdlock(&rwlock);
printf("[%d]: %d\n", id_, data);
pthread_rwlock_unlock(&rwlock);
pthread_yield(); // junk
}
}
private:
static void* _run(void* p) {
Reader* reader = static_cast<Reader*>(p);
reader->run();
return nullptr;
}
};
void writer() {
pthread_yield();
for (;;) {
sleep(1);
printf("rwlock: Acquiring for WRITE\n");
pthread_rwlock_wrlock(&rwlock);
printf("rwlock: hardcore WRITE-action @.@ BEGIN\n");
data = data + 1;
quitting = data == 42;
sleep(2);
printf("rwlock: hardcore WRITE-action @.@ DONE\n");
pthread_rwlock_unlock(&rwlock);
}
}
int main(int argc, const char *argv[])
{
srand(time(nullptr));
std::list<Reader*> readers;
for (int i = 1, e = (argc == 2 ? atoi(argv[1]) : 4); i <= e; ++i)
readers.push_back(new Reader(i));
writer();
for (auto reader: readers)
delete reader;
return 0;
}
struct rwlock
{
volatile uint32_t state;
};
static void __rwlock_init(struct rwlock *lock)
{
lock->state = 0;
}
static void __read_lock(struct rwlock *lock)
{
unsigned int new_state;
unsigned int expected;
do
{
expected = lock->state & 0xffff; /* I expect no write lock */
new_state = expected + 1; /* Add me as reader */
} while (!__sync_bool_compare_and_swap(&(lock->state), expected, new_state));
}
static void __read_unlock(struct rwlock *lock)
{
unsigned int new_state;
unsigned int expected;
do
{
expected = lock->state; /* I expect a write lock and other readers */
new_state = expected - 1; /* Drop me as reader */
} while (!__sync_bool_compare_and_swap(&(lock->state), expected, new_state));
}
static void __write_lock(struct rwlock *lock)
{
unsigned int new_state;
unsigned int expected;
do
{
expected = lock->state & 0xffff; /* I expect some 0+ readers */
new_state = (1 << 16) | expected; /* I want to lock the other writers */
} while (!__sync_bool_compare_and_swap(&(lock->state), expected, new_state));
/* Wait pending reads */
while ((lock->state & 0xffff) > 0) /* cpu_relax(); */
;
}
static void __write_unlock(struct rwlock *lock)
{
unsigned int new_state;
unsigned int expected;
do
{
expected = 1 << 16; /* I expect to be the only writer */
new_state = 0; /* reset: no writers/no readers */
} while (!__sync_bool_compare_and_swap(&(lock->state), expected, new_state));
}