xref: /haiku/src/kits/app/LooperList.cpp (revision 21258e2674226d6aa732321b6f8494841895af5f)
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 
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 	fData.clear();
194 }
195 
196 
197 bool
198 BLooperList::EmptySlotPred(LooperData& data)
199 {
200 	return data.looper == NULL;
201 }
202 
203 
204 void
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 
215 BLooperList::LooperData::LooperData()
216 	:
217 	looper(NULL)
218 {
219 }
220 
221 
222 BLooperList::LooperData::LooperData(BLooper* looper)
223 	:
224 	looper(looper)
225 {
226 }
227 
228 
229 BLooperList::LooperData::LooperData(const LooperData& other)
230 {
231 	*this = other;
232 }
233 
234 
235 BLooperList::LooperData&
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
246 BLooperList::FindLooperPred::operator()(BLooperList::LooperData& data)
247 {
248 	return data.looper && looper == data.looper;
249 }
250 
251 
252 bool
253 BLooperList::FindThreadPred::operator()(LooperData& data)
254 {
255 	return data.looper && thread == data.looper->Thread();
256 }
257 
258 
259 bool
260 BLooperList::FindNamePred::operator()(LooperData& data)
261 {
262 	return data.looper && !strcmp(name, data.looper->Name());
263 }
264 
265 
266 bool
267 BLooperList::FindPortPred::operator()(LooperData& data)
268 {
269 	return data.looper && port == _get_looper_port_(data.looper);
270 }
271 
272 }	// namespace BPrivate
273 
274