#include "NodeHandleMap.h"
#include "AutoLocker.h"
#include "GlobalBlockerPool.h"
NodeHandleMap::NodeHandleMap(const char* name)
: Locker(name),
fNextNodeHandleCookie(0)
{
}
NodeHandleMap::~NodeHandleMap()
{
}
status_t
NodeHandleMap::Init()
{
if (Sem() < 0)
return Sem();
return B_OK;
}
status_t
NodeHandleMap::AddNodeHandle(NodeHandle* handle)
{
if (!handle)
return B_BAD_VALUE;
AutoLocker<Locker> _(this);
handle->SetCookie(_NextNodeHandleCookie());
status_t error = Put(handle->GetCookie(), handle);
if (error == B_OK)
handle->AcquireReference();
return error;
}
bool
NodeHandleMap::RemoveNodeHandle(NodeHandle* handle)
{
if (!handle)
return false;
AutoLocker<Locker> _(this);
if (Get(handle->GetCookie()) != handle)
return false;
Remove(handle->GetCookie());
handle->ReleaseReference();
return true;
}
status_t
NodeHandleMap::LockNodeHandle(int32 cookie, NodeHandle** _handle)
{
if (!_handle)
return B_BAD_VALUE;
NodeHandle* handle;
{
AutoLocker<Locker> _(this);
handle = Get(cookie);
if (!handle)
return B_ENTRY_NOT_FOUND;
handle->AcquireReference();
if (handle->Lock()) {
*_handle = handle;
return B_OK;
}
}
BlockerPool* blockerPool = GlobalBlockerPool::GetDefault();
Blocker blocker = blockerPool->GetBlocker();
BlockerPutter blockerPutter(*blockerPool, blocker);
LockerCandidate lockerCandidate(blocker);
{
AutoLocker<Locker> _(this);
if (handle->Lock()) {
*_handle = handle;
return B_OK;
}
handle->QueueLockerCandidate(&lockerCandidate);
}
status_t error = lockerCandidate.Block();
if (error != B_OK) {
handle->ReleaseReference();
return error;
}
*_handle = handle;
return B_OK;
}
void
NodeHandleMap::UnlockNodeHandle(NodeHandle* nodeHandle)
{
if (!nodeHandle)
return;
if (nodeHandle->IsLocked()) {
AutoLocker<Locker> _(this);
nodeHandle->Unlock();
nodeHandle->ReleaseReference();
}
}
int32
NodeHandleMap::_NextNodeHandleCookie()
{
int32 cookie;
do {
if (fNextNodeHandleCookie < 0)
fNextNodeHandleCookie = 0;
cookie = fNextNodeHandleCookie++;
} while (ContainsKey(cookie));
return cookie;
}