1// Blocker.cpp
2
3#include <new>
4
5#include "Blocker.h"
6
7// Data
8struct Blocker::Data {
9	Data()
10		: semaphore(create_sem(0, "blocker")),
11		  references(1),
12		  userData(0)
13	{
14	}
15
16	Data(sem_id semaphore)
17		: semaphore(semaphore),
18		  references(1)
19	{
20	}
21
22	~Data()
23	{
24		if (semaphore >= 0)
25			delete_sem(semaphore);
26	}
27
28	sem_id	semaphore;
29	int32	references;
30	int32	userData;
31};
32
33// constructor
34Blocker::Blocker()
35	: fData(new(std::nothrow) Data)
36{
37}
38
39// constructor
40Blocker::Blocker(sem_id semaphore)
41	: fData(new(std::nothrow) Data(semaphore))
42{
43	if (!fData)
44		delete_sem(semaphore);
45}
46
47// copy constructor
48Blocker::Blocker(const Blocker& other)
49	: fData(NULL)
50{
51	*this = other;
52}
53
54// destructor
55Blocker::~Blocker()
56{
57	_Unset();
58}
59
60// InitCheck
61status_t
62Blocker::InitCheck() const
63{
64	if (!fData)
65		return B_NO_MEMORY;
66	return (fData->semaphore < 0 ? fData->semaphore : B_OK);
67}
68
69// PrepareForUse
70status_t
71Blocker::PrepareForUse()
72{
73	// check initialization
74	if (!fData || fData->semaphore < 0)
75		return B_NO_INIT;
76	// get semaphore count
77	int32 count;
78	status_t error = get_sem_count(fData->semaphore, &count);
79	if (error != B_OK)
80		return error;
81	// set the semaphore count to zero
82	if (count > 0)
83		error = acquire_sem_etc(fData->semaphore, count, B_RELATIVE_TIMEOUT, 0);
84	else if (count < 0)
85		error = release_sem_etc(fData->semaphore, -count, 0);
86	return error;
87}
88
89// Block
90status_t
91Blocker::Block(int32* userData)
92{
93	if (!fData || fData->semaphore < 0)
94		return B_NO_INIT;
95
96	status_t error = acquire_sem(fData->semaphore);
97
98	if (userData)
99		*userData = fData->userData;
100
101	return error;
102}
103
104// Unblock
105status_t
106Blocker::Unblock(int32 userData)
107{
108	if (!fData || fData->semaphore < 0)
109		return B_NO_INIT;
110
111	fData->userData = userData;
112
113	return release_sem(fData->semaphore);
114}
115
116// =
117Blocker&
118Blocker::operator=(const Blocker& other)
119{
120	_Unset();
121	fData = other.fData;
122	if (fData)
123		fData->references++;
124	return *this;
125}
126
127// ==
128bool
129Blocker::operator==(const Blocker& other) const
130{
131	return (fData == other.fData);
132}
133
134// !=
135bool
136Blocker::operator!=(const Blocker& other) const
137{
138	return (fData != other.fData);
139}
140
141// _Unset
142void
143Blocker::_Unset()
144{
145	if (fData) {
146		if (--fData->references == 0)
147			delete fData;
148		fData = NULL;
149	}
150}
151
152