haiku/src/kits/app/LooperList.cpp

274 lines
4.0 KiB
C++

/*
* Copyright 2001-2015, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Erik Jaesler (erik@cgsoftware.com)
*/
//! Maintains a global list of all loopers in a given team.
#include "LooperList.h"
#include <Autolock.h>
#include <Looper.h>
#include <algorithm>
#include <string.h>
using std::vector;
namespace BPrivate {
BLooperList gLooperList;
BLooperList::BLooperList()
:
fLock("BLooperList lock")
{
}
bool
BLooperList::Lock()
{
return fLock.Lock();
}
void
BLooperList::Unlock()
{
fLock.Unlock();
}
bool
BLooperList::IsLocked()
{
return fLock.IsLocked();
}
void
BLooperList::AddLooper(BLooper* looper)
{
BAutolock locker(fLock);
AssertLocked();
if (!IsLooperValid(looper)) {
LooperDataIterator i
= find_if(fData.begin(), fData.end(), EmptySlotPred);
if (i == fData.end()) {
fData.push_back(LooperData(looper));
looper->Lock();
} else {
i->looper = looper;
looper->Lock();
}
}
}
bool
BLooperList::IsLooperValid(const BLooper* looper)
{
BAutolock locker(fLock);
AssertLocked();
return find_if(fData.begin(), fData.end(),
FindLooperPred(looper)) != fData.end();
}
bool
BLooperList::RemoveLooper(BLooper* looper)
{
BAutolock locker(fLock);
AssertLocked();
LooperDataIterator i = find_if(fData.begin(), fData.end(),
FindLooperPred(looper));
if (i != fData.end()) {
i->looper = NULL;
return true;
}
return false;
}
void
BLooperList::GetLooperList(BList* list)
{
BAutolock locker(fLock);
AssertLocked();
for (uint32 i = 0; i < fData.size(); ++i) {
if (fData[i].looper)
list->AddItem(fData[i].looper);
}
}
int32
BLooperList::CountLoopers()
{
BAutolock locker(fLock);
AssertLocked();
return (int32)fData.size();
}
BLooper*
BLooperList::LooperAt(int32 index)
{
BAutolock locker(fLock);
AssertLocked();
BLooper* looper = NULL;
if (index < (int32)fData.size())
looper = fData[(uint32)index].looper;
return looper;
}
BLooper*
BLooperList::LooperForThread(thread_id thread)
{
BAutolock locker(fLock);
AssertLocked();
BLooper* looper = NULL;
LooperDataIterator i
= find_if(fData.begin(), fData.end(), FindThreadPred(thread));
if (i != fData.end())
looper = i->looper;
return looper;
}
BLooper*
BLooperList::LooperForName(const char* name)
{
BAutolock locker(fLock);
AssertLocked();
BLooper* looper = NULL;
LooperDataIterator i
= find_if(fData.begin(), fData.end(), FindNamePred(name));
if (i != fData.end())
looper = i->looper;
return looper;
}
BLooper*
BLooperList::LooperForPort(port_id port)
{
BAutolock locker(fLock);
AssertLocked();
BLooper* looper = NULL;
LooperDataIterator i
= find_if(fData.begin(), fData.end(), FindPortPred(port));
if (i != fData.end())
looper = i->looper;
return looper;
}
void
BLooperList::InitAfterFork()
{
// We need to reinitialize the locker to get a new semaphore
new (&fLock) BLocker("BLooperList lock");
fData.clear();
}
bool
BLooperList::EmptySlotPred(LooperData& data)
{
return data.looper == NULL;
}
void
BLooperList::AssertLocked()
{
if (!IsLocked())
debugger("looperlist is not locked; proceed at great risk!");
}
// #pragma mark - BLooperList::LooperData
BLooperList::LooperData::LooperData()
:
looper(NULL)
{
}
BLooperList::LooperData::LooperData(BLooper* looper)
:
looper(looper)
{
}
BLooperList::LooperData::LooperData(const LooperData& other)
{
*this = other;
}
BLooperList::LooperData&
BLooperList::LooperData::operator=(const LooperData& other)
{
if (this != &other)
looper = other.looper;
return *this;
}
bool
BLooperList::FindLooperPred::operator()(BLooperList::LooperData& data)
{
return data.looper && looper == data.looper;
}
bool
BLooperList::FindThreadPred::operator()(LooperData& data)
{
return data.looper && thread == data.looper->Thread();
}
bool
BLooperList::FindNamePred::operator()(LooperData& data)
{
return data.looper && !strcmp(name, data.looper->Name());
}
bool
BLooperList::FindPortPred::operator()(LooperData& data)
{
return data.looper && port == _get_looper_port_(data.looper);
}
} // namespace BPrivate