1 /*
2 * Copyright 2001-2015, Haiku.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 * Erik Jaesler (erik@cgsoftware.com)
7 */
8
9
10 //! Maintains a global list of all loopers in a given team.
11
12
13 #include "LooperList.h"
14
15 #include <Autolock.h>
16 #include <Looper.h>
17
18 #include <algorithm>
19 #include <string.h>
20
21
22 using std::vector;
23
24 namespace BPrivate {
25
26 BLooperList gLooperList;
27
28
BLooperList()29 BLooperList::BLooperList()
30 :
31 fLock("BLooperList lock")
32 {
33 }
34
35
36 bool
Lock()37 BLooperList::Lock()
38 {
39 return fLock.Lock();
40 }
41
42
43 void
Unlock()44 BLooperList::Unlock()
45 {
46 fLock.Unlock();
47 }
48
49
50 bool
IsLocked()51 BLooperList::IsLocked()
52 {
53 return fLock.IsLocked();
54 }
55
56
57 void
AddLooper(BLooper * looper)58 BLooperList::AddLooper(BLooper* looper)
59 {
60 BAutolock locker(fLock);
61 AssertLocked();
62 if (!IsLooperValid(looper)) {
63 LooperDataIterator i
64 = find_if(fData.begin(), fData.end(), EmptySlotPred);
65 if (i == fData.end()) {
66 fData.push_back(LooperData(looper));
67 looper->Lock();
68 } else {
69 i->looper = looper;
70 looper->Lock();
71 }
72 }
73 }
74
75
76 bool
IsLooperValid(const BLooper * looper)77 BLooperList::IsLooperValid(const BLooper* looper)
78 {
79 BAutolock locker(fLock);
80 AssertLocked();
81
82 return find_if(fData.begin(), fData.end(),
83 FindLooperPred(looper)) != fData.end();
84 }
85
86
87 bool
RemoveLooper(BLooper * looper)88 BLooperList::RemoveLooper(BLooper* looper)
89 {
90 BAutolock locker(fLock);
91 AssertLocked();
92
93 LooperDataIterator i = find_if(fData.begin(), fData.end(),
94 FindLooperPred(looper));
95 if (i != fData.end()) {
96 i->looper = NULL;
97 return true;
98 }
99
100 return false;
101 }
102
103
104 void
GetLooperList(BList * list)105 BLooperList::GetLooperList(BList* list)
106 {
107 BAutolock locker(fLock);
108 AssertLocked();
109
110 for (uint32 i = 0; i < fData.size(); ++i) {
111 if (fData[i].looper)
112 list->AddItem(fData[i].looper);
113 }
114 }
115
116
117 int32
CountLoopers()118 BLooperList::CountLoopers()
119 {
120 BAutolock locker(fLock);
121 AssertLocked();
122 return (int32)fData.size();
123 }
124
125
126 BLooper*
LooperAt(int32 index)127 BLooperList::LooperAt(int32 index)
128 {
129 BAutolock locker(fLock);
130 AssertLocked();
131
132 BLooper* looper = NULL;
133 if (index < (int32)fData.size())
134 looper = fData[(uint32)index].looper;
135
136 return looper;
137 }
138
139
140 BLooper*
LooperForThread(thread_id thread)141 BLooperList::LooperForThread(thread_id thread)
142 {
143 BAutolock locker(fLock);
144 AssertLocked();
145
146 BLooper* looper = NULL;
147 LooperDataIterator i
148 = find_if(fData.begin(), fData.end(), FindThreadPred(thread));
149 if (i != fData.end())
150 looper = i->looper;
151
152 return looper;
153 }
154
155
156 BLooper*
LooperForName(const char * name)157 BLooperList::LooperForName(const char* name)
158 {
159 BAutolock locker(fLock);
160 AssertLocked();
161
162 BLooper* looper = NULL;
163 LooperDataIterator i
164 = find_if(fData.begin(), fData.end(), FindNamePred(name));
165 if (i != fData.end())
166 looper = i->looper;
167
168 return looper;
169 }
170
171
172 BLooper*
LooperForPort(port_id port)173 BLooperList::LooperForPort(port_id port)
174 {
175 BAutolock locker(fLock);
176 AssertLocked();
177
178 BLooper* looper = NULL;
179 LooperDataIterator i
180 = find_if(fData.begin(), fData.end(), FindPortPred(port));
181 if (i != fData.end())
182 looper = i->looper;
183
184 return looper;
185 }
186
187
188 void
InitAfterFork()189 BLooperList::InitAfterFork()
190 {
191 // We need to reinitialize the locker to get a new semaphore
192 new (&fLock) BLocker("BLooperList lock");
193 fData.clear();
194 }
195
196
197 bool
EmptySlotPred(LooperData & data)198 BLooperList::EmptySlotPred(LooperData& data)
199 {
200 return data.looper == NULL;
201 }
202
203
204 void
AssertLocked()205 BLooperList::AssertLocked()
206 {
207 if (!IsLocked())
208 debugger("looperlist is not locked; proceed at great risk!");
209 }
210
211
212 // #pragma mark - BLooperList::LooperData
213
214
LooperData()215 BLooperList::LooperData::LooperData()
216 :
217 looper(NULL)
218 {
219 }
220
221
LooperData(BLooper * looper)222 BLooperList::LooperData::LooperData(BLooper* looper)
223 :
224 looper(looper)
225 {
226 }
227
228
LooperData(const LooperData & other)229 BLooperList::LooperData::LooperData(const LooperData& other)
230 {
231 *this = other;
232 }
233
234
235 BLooperList::LooperData&
operator =(const LooperData & other)236 BLooperList::LooperData::operator=(const LooperData& other)
237 {
238 if (this != &other)
239 looper = other.looper;
240
241 return *this;
242 }
243
244
245 bool
operator ()(BLooperList::LooperData & data)246 BLooperList::FindLooperPred::operator()(BLooperList::LooperData& data)
247 {
248 return data.looper && looper == data.looper;
249 }
250
251
252 bool
operator ()(LooperData & data)253 BLooperList::FindThreadPred::operator()(LooperData& data)
254 {
255 return data.looper && thread == data.looper->Thread();
256 }
257
258
259 bool
operator ()(LooperData & data)260 BLooperList::FindNamePred::operator()(LooperData& data)
261 {
262 return data.looper && !strcmp(name, data.looper->Name());
263 }
264
265
266 bool
operator ()(LooperData & data)267 BLooperList::FindPortPred::operator()(LooperData& data)
268 {
269 return data.looper && port == _get_looper_port_(data.looper);
270 }
271
272 } // namespace BPrivate
273
274