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
22using std::vector;
23
24namespace BPrivate {
25
26BLooperList gLooperList;
27
28
29BLooperList::BLooperList()
30	:
31	fLock("BLooperList lock")
32{
33}
34
35
36bool
37BLooperList::Lock()
38{
39	return fLock.Lock();
40}
41
42
43void
44BLooperList::Unlock()
45{
46	fLock.Unlock();
47}
48
49
50bool
51BLooperList::IsLocked()
52{
53	return fLock.IsLocked();
54}
55
56
57void
58BLooperList::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
76bool
77BLooperList::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
87bool
88BLooperList::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
104void
105BLooperList::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
117int32
118BLooperList::CountLoopers()
119{
120	BAutolock locker(fLock);
121	AssertLocked();
122	return (int32)fData.size();
123}
124
125
126BLooper*
127BLooperList::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
140BLooper*
141BLooperList::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
156BLooper*
157BLooperList::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
172BLooper*
173BLooperList::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
188void
189BLooperList::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
197bool
198BLooperList::EmptySlotPred(LooperData& data)
199{
200	return data.looper == NULL;
201}
202
203
204void
205BLooperList::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
215BLooperList::LooperData::LooperData()
216	:
217	looper(NULL)
218{
219}
220
221
222BLooperList::LooperData::LooperData(BLooper* looper)
223	:
224	looper(looper)
225{
226}
227
228
229BLooperList::LooperData::LooperData(const LooperData& other)
230{
231	*this = other;
232}
233
234
235BLooperList::LooperData&
236BLooperList::LooperData::operator=(const LooperData& other)
237{
238	if (this != &other)
239		looper = other.looper;
240
241	return *this;
242}
243
244
245bool
246BLooperList::FindLooperPred::operator()(BLooperList::LooperData& data)
247{
248	return data.looper && looper == data.looper;
249}
250
251
252bool
253BLooperList::FindThreadPred::operator()(LooperData& data)
254{
255	return data.looper && thread == data.looper->Thread();
256}
257
258
259bool
260BLooperList::FindNamePred::operator()(LooperData& data)
261{
262	return data.looper && !strcmp(name, data.looper->Name());
263}
264
265
266bool
267BLooperList::FindPortPred::operator()(LooperData& data)
268{
269	return data.looper && port == _get_looper_port_(data.looper);
270}
271
272}	// namespace BPrivate
273
274