haiku/src/system/kernel/Notifications.cpp
Ingo Weinhold 0c615a01ae * Removed old mutex implementation and renamed cutex to mutex.
* Trivial adjustments of code using mutexes. Mostly removing the
  mutex_init() return value check.
* Added mutex_lock_threads_locked(), which is called with the threads
  spinlock being held. The spinlock is released while waiting, of
  course. This function is useful in cases where the existence of the
  mutex object is ensured by holding the threads spinlock.
* Changed the two instances in the VFS code where an IO context of
  another team needs to be locked to use mutex_lock_threads_locked().
  Before it required a semaphore-based mutex implementation.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@25283 a95241bf-73f2-0310-859d-f6bbb57e9c96
2008-05-01 22:07:36 +00:00

282 lines
5.0 KiB
C++

/*
* Copyright 2007, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Axel Dörfler, axeld@pinc-software.de
* Ingo Weinhold, bonefish@cs.tu-berlin.de
*/
#include <Notifications.h>
NotificationManager NotificationManager::sManager;
// #pragma mark - UserMessagingListener
NotificationListener::~NotificationListener()
{
}
void
NotificationListener::EventOccured(NotificationService& service,
const KMessage* event)
{
}
void
NotificationListener::AllListenersNotified(NotificationService& service)
{
}
bool
NotificationListener::operator==(const NotificationListener& other) const
{
return &other == this;
}
// #pragma mark - UserMessagingMessageSender
UserMessagingMessageSender::UserMessagingMessageSender()
:
fMessage(NULL),
fTargetCount(0)
{
}
void
UserMessagingMessageSender::SendMessage(const KMessage* message, port_id port,
int32 token)
{
if (message != fMessage && fMessage != NULL
|| fTargetCount == MAX_MESSAGING_TARGET_COUNT) {
FlushMessage();
}
fMessage = message;
fTargets[fTargetCount].port = port;
fTargets[fTargetCount].token = token;
fTargetCount++;
}
void
UserMessagingMessageSender::FlushMessage()
{
if (fMessage != NULL && fTargetCount > 0) {
send_message(fMessage->Buffer(), fMessage->ContentSize(),
fTargets, fTargetCount);
}
fMessage = NULL;
fTargetCount = 0;
}
// #pragma mark - UserMessagingListener
UserMessagingListener::UserMessagingListener(UserMessagingMessageSender& sender,
port_id port, int32 token)
:
fSender(sender),
fPort(port),
fToken(token)
{
}
UserMessagingListener::~UserMessagingListener()
{
}
void
UserMessagingListener::EventOccured(NotificationService& service,
const KMessage* event)
{
fSender.SendMessage(event, fPort, fToken);
}
void
UserMessagingListener::AllListenersNotified(NotificationService& service)
{
fSender.FlushMessage();
}
// #pragma mark - NotificationService
NotificationService::~NotificationService()
{
}
// #pragma mark - NotificationManager
/*static*/ NotificationManager&
NotificationManager::Manager()
{
return sManager;
}
/*static*/ status_t
NotificationManager::CreateManager()
{
new(&sManager) NotificationManager;
return sManager._Init();
}
NotificationManager::NotificationManager()
{
}
NotificationManager::~NotificationManager()
{
}
status_t
NotificationManager::_Init()
{
mutex_init(&fLock, "notification manager");
return fServiceHash.InitCheck();
}
NotificationService*
NotificationManager::_ServiceFor(const char* name)
{
return fServiceHash.Lookup(name);
}
status_t
NotificationManager::RegisterService(NotificationService& service)
{
MutexLocker _(fLock);
if (_ServiceFor(service.Name()))
return B_NAME_IN_USE;
status_t status = fServiceHash.Insert(&service);
if (status == B_OK)
service.AddReference();
return status;
}
void
NotificationManager::UnregisterService(NotificationService& service)
{
MutexLocker _(fLock);
fServiceHash.Remove(&service);
service.RemoveReference();
}
status_t
NotificationManager::AddListener(const char* serviceName,
uint32 eventMask, NotificationListener& listener)
{
char buffer[96];
KMessage specifier;
specifier.SetTo(buffer, sizeof(buffer), 0);
specifier.AddInt32("event mask", eventMask);
return AddListener(serviceName, &specifier, listener);
}
status_t
NotificationManager::AddListener(const char* serviceName,
const KMessage* eventSpecifier, NotificationListener& listener)
{
MutexLocker locker(fLock);
NotificationService* service = _ServiceFor(serviceName);
if (service == NULL)
return B_NAME_NOT_FOUND;
Reference<NotificationService> reference(service);
locker.Unlock();
return service->AddListener(eventSpecifier, listener);
}
status_t
NotificationManager::UpdateListener(const char* serviceName,
uint32 eventMask, NotificationListener& listener)
{
char buffer[96];
KMessage specifier;
specifier.SetTo(buffer, sizeof(buffer), 0);
specifier.AddInt32("event mask", eventMask);
return UpdateListener(serviceName, &specifier, listener);
}
status_t
NotificationManager::UpdateListener(const char* serviceName,
const KMessage* eventSpecifier, NotificationListener& listener)
{
MutexLocker locker(fLock);
NotificationService* service = _ServiceFor(serviceName);
if (service == NULL)
return B_NAME_NOT_FOUND;
Reference<NotificationService> reference(service);
locker.Unlock();
return service->UpdateListener(eventSpecifier, listener);
}
status_t
NotificationManager::RemoveListener(const char* serviceName,
const KMessage* eventSpecifier, NotificationListener& listener)
{
MutexLocker locker(fLock);
NotificationService* service = _ServiceFor(serviceName);
if (service == NULL)
return B_NAME_NOT_FOUND;
Reference<NotificationService> reference(service);
locker.Unlock();
return service->RemoveListener(eventSpecifier, listener);
}
// #pragma mark -
extern "C" void
notifications_init(void)
{
status_t status = NotificationManager::CreateManager();
if (status < B_OK) {
panic("Creating the notification manager failed: %s\n",
strerror(status));
}
}