haiku/src/apps/powerstatus/DriverInterface.cpp

150 lines
2.4 KiB
C++

/*
* Copyright 2009-2015, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Clemens Zeidler, haiku@Clemens-Zeidler.de
*/
#include "DriverInterface.h"
#include <Autolock.h>
#include <Messenger.h>
Monitor::~Monitor()
{
}
status_t
Monitor::StartWatching(BHandler* target)
{
if (fWatcherList.HasItem(target))
return B_ERROR;
fWatcherList.AddItem(target);
return B_OK;
}
status_t
Monitor::StopWatching(BHandler* target)
{
return fWatcherList.RemoveItem(target);
}
void
Monitor::Broadcast(uint32 message)
{
for (int i = 0; i < fWatcherList.CountItems(); i++) {
BMessenger messenger(fWatcherList.ItemAt(i));
messenger.SendMessage(message);
}
}
// #pragma mark -
PowerStatusDriverInterface::PowerStatusDriverInterface()
:
fIsWatching(0),
fWaitSem(-1),
fThread(-1),
fListLocker("driver list")
{
}
PowerStatusDriverInterface::~PowerStatusDriverInterface()
{
}
status_t
PowerStatusDriverInterface::StartWatching(BHandler* target)
{
BAutolock autolock(fListLocker);
status_t status = Monitor::StartWatching(target);
if (status != B_OK)
return status;
if (fThread > 0)
return B_OK;
fThread = spawn_thread(&_ThreadWatchPowerFunction, "PowerStatusThread",
B_LOW_PRIORITY, this);
if (fThread >= 0) {
fWaitSem = create_sem(0, "power status wait");
atomic_set(&fIsWatching, 1);
status = resume_thread(fThread);
} else
return fThread;
if (status != B_OK && fWatcherList.CountItems() == 0) {
atomic_set(&fIsWatching, 0);
delete_sem(fWaitSem);
fThread = -1;
fWaitSem = -1;
}
return status;
}
status_t
PowerStatusDriverInterface::StopWatching(BHandler* target)
{
if (fThread < 0)
return B_BAD_VALUE;
fListLocker.Lock();
if (fWatcherList.CountItems() == 1) {
fListLocker.Unlock();
Disconnect();
} else
fListLocker.Unlock();
return Monitor::StopWatching(target);
}
void
PowerStatusDriverInterface::Broadcast(uint32 message)
{
BAutolock autolock(fListLocker);
Monitor::Broadcast(message);
}
void
PowerStatusDriverInterface::Disconnect()
{
if (fThread < 0)
return;
atomic_set(&fIsWatching, 0);
delete_sem(fWaitSem);
wait_for_thread(fThread, NULL);
fThread = -1;
fWaitSem = -1;
}
int32
PowerStatusDriverInterface::_ThreadWatchPowerFunction(void* data)
{
PowerStatusDriverInterface* that = (PowerStatusDriverInterface*)data;
that->_WatchPowerStatus();
return 0;
}