xref: /haiku/src/kits/app/LooperList.cpp (revision 778611c7e6a61b8ba072212756ce53eda826360a)
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 
29 BLooperList::BLooperList()
30 	:
31 	fLock("BLooperList lock")
32 {
33 }
34 
35 
36 bool
37 BLooperList::Lock()
38 {
39 	return fLock.Lock();
40 }
41 
42 
43 void
44 BLooperList::Unlock()
45 {
46 	fLock.Unlock();
47 }
48 
49 
50 bool
51 BLooperList::IsLocked()
52 {
53 	return fLock.IsLocked();
54 }
55 
56 
57 void
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
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
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
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
118 BLooperList::CountLoopers()
119 {
120 	BAutolock locker(fLock);
121 	AssertLocked();
122 	return (int32)fData.size();
123 }
124 
125 
126 BLooper*
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*
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*
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*
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
189 BLooperList::InitAfterFork()
190 {
191 	// We need to reinitialize the locker to get a new semaphore
192 	new (&fLock) BLocker("BLooperList lock");
193 }
194 
195 
196 bool
197 BLooperList::EmptySlotPred(LooperData& data)
198 {
199 	return data.looper == NULL;
200 }
201 
202 
203 void
204 BLooperList::AssertLocked()
205 {
206 	if (!IsLocked())
207 		debugger("looperlist is not locked; proceed at great risk!");
208 }
209 
210 
211 //	#pragma mark - BLooperList::LooperData
212 
213 
214 BLooperList::LooperData::LooperData()
215 	:
216 	looper(NULL)
217 {
218 }
219 
220 
221 BLooperList::LooperData::LooperData(BLooper* looper)
222 	:
223 	looper(looper)
224 {
225 }
226 
227 
228 BLooperList::LooperData::LooperData(const LooperData& other)
229 {
230 	*this = other;
231 }
232 
233 
234 BLooperList::LooperData&
235 BLooperList::LooperData::operator=(const LooperData& other)
236 {
237 	if (this != &other)
238 		looper = other.looper;
239 
240 	return *this;
241 }
242 
243 
244 bool
245 BLooperList::FindLooperPred::operator()(BLooperList::LooperData& data)
246 {
247 	return data.looper && looper == data.looper;
248 }
249 
250 
251 bool
252 BLooperList::FindThreadPred::operator()(LooperData& data)
253 {
254 	return data.looper && thread == data.looper->Thread();
255 }
256 
257 
258 bool
259 BLooperList::FindNamePred::operator()(LooperData& data)
260 {
261 	return data.looper && !strcmp(name, data.looper->Name());
262 }
263 
264 
265 bool
266 BLooperList::FindPortPred::operator()(LooperData& data)
267 {
268 	return data.looper && port == _get_looper_port_(data.looper);
269 }
270 
271 }	// namespace BPrivate
272 
273