474d27da32
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
132 lines
2.6 KiB
C++
132 lines
2.6 KiB
C++
/*
|
|
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
|
* 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
|