xref: /haiku/src/add-ons/kernel/file_systems/netfs/shared/Blocker.cpp (revision 1deede7388b04dbeec5af85cae7164735ea9e70d)
1 // Blocker.cpp
2 
3 #include <new>
4 
5 #include "Blocker.h"
6 
7 // Data
8 struct 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
34 Blocker::Blocker()
35 	: fData(new(std::nothrow) Data)
36 {
37 }
38 
39 // constructor
40 Blocker::Blocker(sem_id semaphore)
41 	: fData(new(std::nothrow) Data(semaphore))
42 {
43 	if (!fData)
44 		delete_sem(semaphore);
45 }
46 
47 // copy constructor
48 Blocker::Blocker(const Blocker& other)
49 	: fData(NULL)
50 {
51 	*this = other;
52 }
53 
54 // destructor
55 Blocker::~Blocker()
56 {
57 	_Unset();
58 }
59 
60 // InitCheck
61 status_t
62 Blocker::InitCheck() const
63 {
64 	if (!fData)
65 		return B_NO_MEMORY;
66 	return (fData->semaphore < 0 ? fData->semaphore : B_OK);
67 }
68 
69 // PrepareForUse
70 status_t
71 Blocker::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
90 status_t
91 Blocker::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
105 status_t
106 Blocker::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 // =
117 Blocker&
118 Blocker::operator=(const Blocker& other)
119 {
120 	_Unset();
121 	fData = other.fData;
122 	if (fData)
123 		fData->references++;
124 	return *this;
125 }
126 
127 // ==
128 bool
129 Blocker::operator==(const Blocker& other) const
130 {
131 	return (fData == other.fData);
132 }
133 
134 // !=
135 bool
136 Blocker::operator!=(const Blocker& other) const
137 {
138 	return (fData != other.fData);
139 }
140 
141 // _Unset
142 void
143 Blocker::_Unset()
144 {
145 	if (fData) {
146 		if (--fData->references == 0)
147 			delete fData;
148 		fData = NULL;
149 	}
150 }
151 
152