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