Added RWLockable and RWLockManager classes. The former is basically a
light-weight read-write lock, that doesn't use a semaphore itself. Locking and unlocking has to be done via methods of RWLockManager. This combo allows lots of locks without risking to hit the semaphore limit. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@29686 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -0,0 +1,131 @@
|
||||
/*
|
||||
* Copyright 2009, Ingo Weinhold, [email protected].
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef _RW_LOCK_MANAGER_H
|
||||
#define _RW_LOCK_MANAGER_H
|
||||
|
||||
#include <Locker.h>
|
||||
|
||||
#include <util/DoublyLinkedList.h>
|
||||
|
||||
|
||||
namespace BPrivate {
|
||||
|
||||
|
||||
class RWLockManager;
|
||||
|
||||
|
||||
class RWLockable {
|
||||
public:
|
||||
RWLockable();
|
||||
|
||||
private:
|
||||
struct Waiter : DoublyLinkedListLinkImpl<Waiter> {
|
||||
Waiter(bool writer)
|
||||
:
|
||||
thread(find_thread(NULL)),
|
||||
writer(writer),
|
||||
queued(false)
|
||||
{
|
||||
}
|
||||
|
||||
thread_id thread;
|
||||
status_t status;
|
||||
bool writer;
|
||||
bool queued;
|
||||
};
|
||||
|
||||
typedef DoublyLinkedList<Waiter> WaiterList;
|
||||
|
||||
friend class RWLockManager;
|
||||
|
||||
private:
|
||||
thread_id fOwner;
|
||||
int32 fOwnerCount;
|
||||
int32 fReaderCount;
|
||||
WaiterList fWaiters;
|
||||
};
|
||||
|
||||
|
||||
class RWLockManager {
|
||||
public:
|
||||
RWLockManager();
|
||||
~RWLockManager();
|
||||
|
||||
status_t Init() { return fLock.InitCheck(); }
|
||||
|
||||
bool Lock() { return fLock.Lock(); }
|
||||
void Unlock() { return fLock.Unlock(); }
|
||||
|
||||
bool ReadLock(RWLockable* lockable);
|
||||
bool TryReadLock(RWLockable* lockable);
|
||||
status_t ReadLockWithTimeout(RWLockable* lockable,
|
||||
bigtime_t timeout);
|
||||
void ReadUnlock(RWLockable* lockable);
|
||||
|
||||
bool WriteLock(RWLockable* lockable);
|
||||
bool TryWriteLock(RWLockable* lockable);
|
||||
status_t WriteLockWithTimeout(RWLockable* lockable,
|
||||
bigtime_t timeout);
|
||||
void WriteUnlock(RWLockable* lockable);
|
||||
|
||||
inline bool GenericLock(bool write, RWLockable* lockable);
|
||||
inline bool TryGenericLock(bool write,
|
||||
RWLockable* lockable);
|
||||
inline status_t GenericLockWithTimeout(bool write,
|
||||
RWLockable* lockable, bigtime_t timeout);
|
||||
inline void GenericUnlock(bool write, RWLockable* lockable);
|
||||
|
||||
private:
|
||||
status_t _Wait(RWLockable* lockable, bool writer,
|
||||
bigtime_t timeout);
|
||||
void _Unblock(RWLockable* lockable);
|
||||
|
||||
private:
|
||||
BLocker fLock;
|
||||
};
|
||||
|
||||
|
||||
inline bool
|
||||
RWLockManager::GenericLock(bool write, RWLockable* lockable)
|
||||
{
|
||||
return write ? WriteLock(lockable) : ReadLock(lockable);
|
||||
}
|
||||
|
||||
|
||||
inline bool
|
||||
RWLockManager::TryGenericLock(bool write, RWLockable* lockable)
|
||||
{
|
||||
return write ? TryWriteLock(lockable) : TryReadLock(lockable);
|
||||
}
|
||||
|
||||
|
||||
inline status_t
|
||||
RWLockManager::GenericLockWithTimeout(bool write, RWLockable* lockable,
|
||||
bigtime_t timeout)
|
||||
{
|
||||
return write
|
||||
? WriteLockWithTimeout(lockable, timeout)
|
||||
: ReadLockWithTimeout(lockable, timeout);
|
||||
}
|
||||
|
||||
|
||||
inline void
|
||||
RWLockManager::GenericUnlock(bool write, RWLockable* lockable)
|
||||
{
|
||||
if (write)
|
||||
WriteUnlock(lockable);
|
||||
else
|
||||
ReadUnlock(lockable);
|
||||
}
|
||||
|
||||
|
||||
} // namespace BPrivate
|
||||
|
||||
|
||||
using BPrivate::RWLockable;
|
||||
using BPrivate::RWLockManager;
|
||||
|
||||
|
||||
#endif // _RW_LOCK_MANAGER_H
|
||||
Reference in New Issue
Block a user