#include <new>
#include "AutoLocker.h"
#include "BlockerPool.h"
#include "Vector.h"
struct BlockerPool::BlockerVector : Vector<Blocker> {
};
BlockerPool::BlockerPool(int32 count)
: Locker("blocker pool"),
fFreeBlockersSemaphore(-1),
fBlockers(NULL),
fInitStatus(B_NO_INIT)
{
fInitStatus = _Init(count);
if (fInitStatus != B_OK)
_Unset();
}
BlockerPool::~BlockerPool()
{
_Unset();
}
status_t
BlockerPool::InitCheck() const
{
return fInitStatus;
}
Blocker
BlockerPool::GetBlocker()
{
if (fInitStatus != B_OK)
return B_NO_INIT;
status_t error = acquire_sem(fFreeBlockersSemaphore);
if (error != B_OK)
return error;
AutoLocker<BlockerPool> _(this);
if (fInitStatus != B_OK)
return fInitStatus;
Blocker blocker = fBlockers->ElementAt(fBlockers->Count() - 1);
fBlockers->Erase(fBlockers->Count() - 1);
return blocker;
}
status_t
BlockerPool::PutBlocker(Blocker blocker)
{
status_t error = blocker.PrepareForUse();
if (error != B_OK)
return error;
AutoLocker<BlockerPool> _(this);
if (fInitStatus != B_OK)
return fInitStatus;
error = fBlockers->PushBack(blocker);
if (error != B_OK)
return error;
return release_sem(fFreeBlockersSemaphore);
}
status_t
BlockerPool::_Init(int32 count)
{
_Unset();
AutoLocker<BlockerPool> locker(this);
if (!locker.IsLocked())
return B_ERROR;
fFreeBlockersSemaphore = create_sem(0, "blocker pool free blockers");
if (fFreeBlockersSemaphore < 0)
return fFreeBlockersSemaphore;
fBlockers = new(std::nothrow) BlockerVector;
if (!fBlockers)
return B_NO_MEMORY;
fInitStatus = B_OK;
for (int32 i = 0; i < count; i++) {
Blocker blocker;
status_t error = blocker.InitCheck();
if (error != B_OK)
return error;
error = PutBlocker(blocker);
if (error != B_OK)
return error;
}
return B_OK;
}
void
BlockerPool::_Unset()
{
AutoLocker<BlockerPool> locker(this);
if (fInitStatus == B_OK)
fInitStatus = B_NO_INIT;
delete fBlockers;
fBlockers = NULL;
if (fFreeBlockersSemaphore >= 0)
delete_sem(fFreeBlockersSemaphore);
fFreeBlockersSemaphore = -1;
}