1// BlockerPool.cpp
2
3#include <new>
4
5#include "AutoLocker.h"
6#include "BlockerPool.h"
7#include "Vector.h"
8
9// BlockerVector
10struct BlockerPool::BlockerVector : Vector<Blocker> {
11};
12
13// constructor
14BlockerPool::BlockerPool(int32 count)
15	: Locker("blocker pool"),
16	  fFreeBlockersSemaphore(-1),
17	  fBlockers(NULL),
18	  fInitStatus(B_NO_INIT)
19{
20	fInitStatus = _Init(count);
21	if (fInitStatus != B_OK)
22		_Unset();
23}
24
25// destructor
26BlockerPool::~BlockerPool()
27{
28	_Unset();
29}
30
31// InitCheck
32status_t
33BlockerPool::InitCheck() const
34{
35	return fInitStatus;
36}
37
38// GetBlocker
39Blocker
40BlockerPool::GetBlocker()
41{
42	if (fInitStatus != B_OK)
43		return B_NO_INIT;
44	status_t error = acquire_sem(fFreeBlockersSemaphore);
45	if (error != B_OK)
46		return error;
47	AutoLocker<BlockerPool> _(this);
48	if (fInitStatus != B_OK)
49		return fInitStatus;
50	Blocker blocker = fBlockers->ElementAt(fBlockers->Count() - 1);
51	fBlockers->Erase(fBlockers->Count() - 1);
52	return blocker;
53}
54
55// PutBlocker
56status_t
57BlockerPool::PutBlocker(Blocker blocker)
58{
59	status_t error = blocker.PrepareForUse();
60	if (error != B_OK)
61		return error;
62	AutoLocker<BlockerPool> _(this);
63	if (fInitStatus != B_OK)
64		return fInitStatus;
65	error = fBlockers->PushBack(blocker);
66	if (error != B_OK)
67		return error;
68	return release_sem(fFreeBlockersSemaphore);
69}
70
71// _Init
72status_t
73BlockerPool::_Init(int32 count)
74{
75	_Unset();
76	AutoLocker<BlockerPool> locker(this);
77	if (!locker.IsLocked())
78		return B_ERROR;
79	// create semaphore
80	fFreeBlockersSemaphore = create_sem(0, "blocker pool free blockers");
81	if (fFreeBlockersSemaphore < 0)
82		return fFreeBlockersSemaphore;
83	// allocate blocker vector
84	fBlockers = new(std::nothrow) BlockerVector;
85	if (!fBlockers)
86		return B_NO_MEMORY;
87	fInitStatus = B_OK;
88	// create and add blockers
89	for (int32 i = 0; i < count; i++) {
90		Blocker blocker;
91		status_t error = blocker.InitCheck();
92		if (error != B_OK)
93			return error;
94		error = PutBlocker(blocker);
95		if (error != B_OK)
96			return error;
97	}
98	return B_OK;
99}
100
101// _Unset
102void
103BlockerPool::_Unset()
104{
105	AutoLocker<BlockerPool> locker(this);
106	if (fInitStatus == B_OK)
107		fInitStatus = B_NO_INIT;
108	delete fBlockers;
109	fBlockers = NULL;
110	if (fFreeBlockersSemaphore >= 0)
111		delete_sem(fFreeBlockersSemaphore);
112	fFreeBlockersSemaphore = -1;
113}
114
115