relock 的实现比较简单,是依靠原子量来实现的
skynet 利用内置的原子操作来实现的一个读写锁,重点是理解 ”full memory barrier“。
#ifndef SKYNET_RWLOCK_H | |
#define SKYNET_RWLOCK_H | |
#ifndef USE_PTHREAD_LOCK | |
struct rwlock { | |
int write;// 值为 1 则说明写被锁了 | |
int read; // 读锁的引用计数,不为 0 则说明有别人锁了读 | |
}; | |
static inline void | |
rwlock_init(struct rwlock *lock) { | |
lock->write = 0; | |
lock->read = 0; | |
} | |
static inline void | |
rwlock_rlock(struct rwlock *lock) { | |
for (;;) { | |
while(lock->write) { | |
__sync_synchronize(); | |
} | |
__sync_add_and_fetch(&lock->read,1); | |
if (lock->write) { | |
__sync_sub_and_fetch(&lock->read,1); | |
} else { | |
break; | |
} | |
} | |
} | |
static inline void | |
rwlock_wlock(struct rwlock *lock) { | |
while (__sync_lock_test_and_set(&lock->write,1)) {} | |
while(lock->read) { | |
__sync_synchronize(); | |
} | |
} | |
static inline void | |
rwlock_wunlock(struct rwlock *lock) { | |
__sync_lock_release(&lock->write); | |
} | |
static inline void | |
rwlock_runlock(struct rwlock *lock) { | |
__sync_sub_and_fetch(&lock->read,1); | |
} | |
#else | |
#include <pthread.h> | |
// only for some platform doesn't have __sync_* | |
// todo: check the result of pthread api | |
struct rwlock { | |
pthread_rwlock_t lock; | |
}; | |
static inline void | |
rwlock_init(struct rwlock *lock) { | |
pthread_rwlock_init(&lock->lock, NULL); | |
} | |
static inline void | |
rwlock_rlock(struct rwlock *lock) { | |
pthread_rwlock_rdlock(&lock->lock); | |
} | |
static inline void | |
rwlock_wlock(struct rwlock *lock) { | |
pthread_rwlock_wrlock(&lock->lock); | |
} | |
static inline void | |
rwlock_wunlock(struct rwlock *lock) { | |
pthread_rwlock_unlock(&lock->lock); | |
} | |
static inline void | |
rwlock_runlock(struct rwlock *lock) { | |
pthread_rwlock_unlock(&lock->lock); | |
} | |
#endif | |
#endif |