#include "Lockable.h"
LockerCandidate::LockerCandidate(Blocker blocker)
: fBlocker(blocker),
fThread(find_thread(NULL))
{
}
thread_id
LockerCandidate::GetThread() const
{
return fThread;
}
status_t
LockerCandidate::Block()
{
int32 userData;
status_t error = fBlocker.Block(&userData);
if (error != B_OK)
return error;
return (userData ? B_OK : B_ENTRY_NOT_FOUND);
}
status_t
LockerCandidate::Unblock(bool success)
{
return fBlocker.Unblock(success);
}
Lockable::Lockable()
: fLockOwner(-1),
fLockCounter(0)
{
}
Lockable::~Lockable()
{
while (LockerCandidate* candidate = fLockerCandidates.First()) {
fLockerCandidates.Remove(candidate);
candidate->Unblock(false);
}
}
bool
Lockable::Lock()
{
thread_id thread = find_thread(NULL);
if (fLockOwner >= 0 && fLockOwner != thread)
return false;
fLockOwner = thread;
fLockCounter++;
return true;
}
void
Lockable::Unlock()
{
thread_id thread = find_thread(NULL);
if (fLockOwner != thread)
return;
if (--fLockCounter > 0)
return;
if (LockerCandidate* candidate = fLockerCandidates.First()) {
fLockerCandidates.Remove(candidate);
fLockOwner = candidate->GetThread();
fLockCounter = 1;
candidate->Unblock(true);
} else
fLockOwner = -1;
}
bool
Lockable::IsLocked() const
{
return (fLockOwner == find_thread(NULL));
}
void
Lockable::QueueLockerCandidate(LockerCandidate* candidate)
{
if (!candidate)
return;
if (fLockOwner >= 0) {
fLockerCandidates.Insert(candidate);
} else {
fLockOwner = candidate->GetThread();
fLockCounter = 1;
candidate->Unblock(true);
}
}