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