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