2 * Copyright 2007-2009, Haiku, Inc. All Rights Reserved.
3 * Distributed under the terms of the MIT License.
6 * Axel Dörfler, axeld@pinc-software.de
7 * Ingo Weinhold, bonefish@cs.tu-berlin.de
11 #include <Notifications.h>
20 static const char* kEventMaskString
= "event mask";
22 NotificationManager
NotificationManager::sManager
;
27 // #pragma mark - NotificationListener
30 NotificationListener::~NotificationListener()
36 NotificationListener::EventOccurred(NotificationService
& service
,
37 const KMessage
* event
)
43 NotificationListener::AllListenersNotified(NotificationService
& service
)
49 NotificationListener::operator==(const NotificationListener
& other
) const
51 return &other
== this;
55 // #pragma mark - UserMessagingMessageSender
61 UserMessagingMessageSender::UserMessagingMessageSender()
70 UserMessagingMessageSender::SendMessage(const KMessage
* message
, port_id port
,
73 if ((message
!= fMessage
&& fMessage
!= NULL
)
74 || fTargetCount
== MAX_MESSAGING_TARGET_COUNT
) {
79 fTargets
[fTargetCount
].port
= port
;
80 fTargets
[fTargetCount
].token
= token
;
86 UserMessagingMessageSender::FlushMessage()
88 if (fMessage
!= NULL
&& fTargetCount
> 0) {
89 send_message(fMessage
->Buffer(), fMessage
->ContentSize(),
90 fTargets
, fTargetCount
);
98 // #pragma mark - UserMessagingListener
101 UserMessagingListener::UserMessagingListener(UserMessagingMessageSender
& sender
,
102 port_id port
, int32 token
)
111 UserMessagingListener::~UserMessagingListener()
117 UserMessagingListener::EventOccurred(NotificationService
& service
,
118 const KMessage
* event
)
120 fSender
.SendMessage(event
, fPort
, fToken
);
125 UserMessagingListener::AllListenersNotified(NotificationService
& service
)
127 fSender
.FlushMessage();
131 // #pragma mark - NotificationService
134 NotificationService::~NotificationService()
139 // #pragma mark - default_listener
142 default_listener::~default_listener()
144 // Only delete the listener if it's one of ours
145 if (dynamic_cast<UserMessagingListener
*>(listener
) != NULL
) {
151 // #pragma mark - DefaultNotificationService
154 DefaultNotificationService::DefaultNotificationService(const char* name
)
158 recursive_lock_init(&fLock
, name
);
162 DefaultNotificationService::~DefaultNotificationService()
164 recursive_lock_destroy(&fLock
);
168 /*! \brief Notifies all registered listeners.
169 \param event The message defining the event
170 \param eventMask Only listeners with an event mask sharing at least one
171 common bit with this mask will receive the event.
174 DefaultNotificationService::NotifyLocked(const KMessage
& event
, uint32 eventMask
)
176 // Note: The following iterations support that the listener removes itself
177 // in the hook method. That's a property of the DoublyLinkedList iterator.
179 // notify all listeners about the event
180 DefaultListenerList::Iterator iterator
= fListeners
.GetIterator();
181 while (default_listener
* listener
= iterator
.Next()) {
182 if ((eventMask
& listener
->eventMask
) != 0)
183 listener
->listener
->EventOccurred(*this, &event
);
186 // notify all listeners that all listeners have been notified
187 iterator
= fListeners
.GetIterator();
188 while (default_listener
* listener
= iterator
.Next()) {
189 if ((eventMask
& listener
->eventMask
) != 0)
190 listener
->listener
->AllListenersNotified(*this);
196 DefaultNotificationService::AddListener(const KMessage
* eventSpecifier
,
197 NotificationListener
& notificationListener
)
199 if (eventSpecifier
== NULL
)
203 status_t status
= ToEventMask(*eventSpecifier
, eventMask
);
207 default_listener
* listener
= new(std::nothrow
) default_listener
;
208 if (listener
== NULL
)
211 listener
->eventMask
= eventMask
;
213 listener
->listener
= ¬ificationListener
;
215 RecursiveLocker
_(fLock
);
216 if (fListeners
.IsEmpty())
218 fListeners
.Add(listener
);
225 DefaultNotificationService::UpdateListener(const KMessage
* eventSpecifier
,
226 NotificationListener
& notificationListener
)
228 return B_NOT_SUPPORTED
;
233 DefaultNotificationService::RemoveListener(const KMessage
* eventSpecifier
,
234 NotificationListener
& notificationListener
)
236 RecursiveLocker
_(fLock
);
238 DefaultListenerList::Iterator iterator
= fListeners
.GetIterator();
239 while (default_listener
* listener
= iterator
.Next()) {
240 if (listener
->listener
== ¬ificationListener
) {
244 if (fListeners
.IsEmpty())
250 return B_ENTRY_NOT_FOUND
;
255 DefaultNotificationService::Register()
257 return NotificationManager::Manager().RegisterService(*this);
262 DefaultNotificationService::Unregister()
264 NotificationManager::Manager().UnregisterService(*this);
269 DefaultNotificationService::ToEventMask(const KMessage
& eventSpecifier
,
272 return eventSpecifier
.FindInt32("event mask", (int32
*)&eventMask
);
277 DefaultNotificationService::FirstAdded()
283 DefaultNotificationService::LastRemoved()
288 // #pragma mark - DefaultUserNotificationService
291 DefaultUserNotificationService::DefaultUserNotificationService(const char* name
)
292 : DefaultNotificationService(name
)
294 NotificationManager::Manager().AddListener("teams", TEAM_REMOVED
, *this);
298 DefaultUserNotificationService::~DefaultUserNotificationService()
300 NotificationManager::Manager().RemoveListener("teams", NULL
, *this);
305 DefaultUserNotificationService::AddListener(const KMessage
* eventSpecifier
,
306 NotificationListener
& listener
)
308 if (eventSpecifier
== NULL
)
311 uint32 eventMask
= eventSpecifier
->GetInt32(kEventMaskString
, 0);
313 return _AddListener(eventMask
, listener
);
318 DefaultUserNotificationService::UpdateListener(const KMessage
* eventSpecifier
,
319 NotificationListener
& notificationListener
)
321 if (eventSpecifier
== NULL
)
324 uint32 eventMask
= eventSpecifier
->GetInt32(kEventMaskString
, 0);
325 bool addEvents
= eventSpecifier
->GetBool("add events", false);
327 RecursiveLocker
_(fLock
);
329 DefaultListenerList::Iterator iterator
= fListeners
.GetIterator();
330 while (default_listener
* listener
= iterator
.Next()) {
331 if (*listener
->listener
== notificationListener
) {
333 listener
->eventMask
|= eventMask
;
335 listener
->eventMask
= eventMask
;
340 return B_ENTRY_NOT_FOUND
;
345 DefaultUserNotificationService::RemoveListener(const KMessage
* eventSpecifier
,
346 NotificationListener
& notificationListener
)
348 RecursiveLocker
_(fLock
);
350 DefaultListenerList::Iterator iterator
= fListeners
.GetIterator();
351 while (default_listener
* listener
= iterator
.Next()) {
352 if (listener
->listener
== ¬ificationListener
) {
359 return B_ENTRY_NOT_FOUND
;
364 DefaultUserNotificationService::RemoveUserListeners(port_id port
, uint32 token
)
366 UserMessagingListener
userListener(fSender
, port
, token
);
368 RecursiveLocker
_(fLock
);
370 DefaultListenerList::Iterator iterator
= fListeners
.GetIterator();
371 while (default_listener
* listener
= iterator
.Next()) {
372 if (*listener
->listener
== userListener
) {
376 if (fListeners
.IsEmpty())
382 return B_ENTRY_NOT_FOUND
;
387 DefaultUserNotificationService::UpdateUserListener(uint32 eventMask
,
388 port_id port
, uint32 token
)
390 UserMessagingListener
userListener(fSender
, port
, token
);
392 RecursiveLocker
_(fLock
);
394 DefaultListenerList::Iterator iterator
= fListeners
.GetIterator();
395 while (default_listener
* listener
= iterator
.Next()) {
396 if (*listener
->listener
== userListener
) {
397 listener
->eventMask
|= eventMask
;
402 UserMessagingListener
* copiedListener
403 = new(std::nothrow
) UserMessagingListener(userListener
);
404 if (copiedListener
== NULL
)
407 status_t status
= _AddListener(eventMask
, *copiedListener
);
409 delete copiedListener
;
416 DefaultUserNotificationService::EventOccurred(NotificationService
& service
,
417 const KMessage
* event
)
419 int32 eventCode
= event
->GetInt32("event", -1);
420 team_id team
= event
->GetInt32("team", -1);
422 if (eventCode
== TEAM_REMOVED
&& team
>= B_OK
) {
423 // check if we have any listeners from that team, and remove them
424 RecursiveLocker
_(fLock
);
426 DefaultListenerList::Iterator iterator
= fListeners
.GetIterator();
427 while (default_listener
* listener
= iterator
.Next()) {
428 if (listener
->team
== team
) {
438 DefaultUserNotificationService::AllListenersNotified(
439 NotificationService
& service
)
445 DefaultUserNotificationService::_AddListener(uint32 eventMask
,
446 NotificationListener
& notificationListener
)
448 default_listener
* listener
= new(std::nothrow
) default_listener
;
449 if (listener
== NULL
)
452 listener
->eventMask
= eventMask
;
453 listener
->team
= team_get_current_team_id();
454 listener
->listener
= ¬ificationListener
;
456 RecursiveLocker
_(fLock
);
457 if (fListeners
.IsEmpty())
459 fListeners
.Add(listener
);
465 // #pragma mark - NotificationManager
468 /*static*/ NotificationManager
&
469 NotificationManager::Manager()
476 NotificationManager::CreateManager()
478 new(&sManager
) NotificationManager
;
479 return sManager
._Init();
483 NotificationManager::NotificationManager()
488 NotificationManager::~NotificationManager()
494 NotificationManager::_Init()
496 mutex_init(&fLock
, "notification manager");
498 return fServiceHash
.Init();
503 NotificationManager::_ServiceFor(const char* name
)
505 return fServiceHash
.Lookup(name
);
510 NotificationManager::RegisterService(NotificationService
& service
)
512 MutexLocker
_(fLock
);
514 if (_ServiceFor(service
.Name()))
515 return B_NAME_IN_USE
;
517 status_t status
= fServiceHash
.Insert(&service
);
519 service
.AcquireReference();
526 NotificationManager::UnregisterService(NotificationService
& service
)
528 MutexLocker
_(fLock
);
529 fServiceHash
.Remove(&service
);
530 service
.ReleaseReference();
535 NotificationManager::AddListener(const char* serviceName
,
536 uint32 eventMask
, NotificationListener
& listener
)
540 specifier
.SetTo(buffer
, sizeof(buffer
), 0);
541 specifier
.AddInt32(kEventMaskString
, eventMask
);
543 return AddListener(serviceName
, &specifier
, listener
);
548 NotificationManager::AddListener(const char* serviceName
,
549 const KMessage
* eventSpecifier
, NotificationListener
& listener
)
551 MutexLocker
locker(fLock
);
552 NotificationService
* service
= _ServiceFor(serviceName
);
554 return B_NAME_NOT_FOUND
;
556 BReference
<NotificationService
> reference(service
);
559 return service
->AddListener(eventSpecifier
, listener
);
564 NotificationManager::UpdateListener(const char* serviceName
,
565 uint32 eventMask
, NotificationListener
& listener
)
569 specifier
.SetTo(buffer
, sizeof(buffer
), 0);
570 specifier
.AddInt32(kEventMaskString
, eventMask
);
572 return UpdateListener(serviceName
, &specifier
, listener
);
577 NotificationManager::UpdateListener(const char* serviceName
,
578 const KMessage
* eventSpecifier
, NotificationListener
& listener
)
580 MutexLocker
locker(fLock
);
581 NotificationService
* service
= _ServiceFor(serviceName
);
583 return B_NAME_NOT_FOUND
;
585 BReference
<NotificationService
> reference(service
);
588 return service
->UpdateListener(eventSpecifier
, listener
);
593 NotificationManager::RemoveListener(const char* serviceName
,
594 const KMessage
* eventSpecifier
, NotificationListener
& listener
)
596 MutexLocker
locker(fLock
);
597 NotificationService
* service
= _ServiceFor(serviceName
);
599 return B_NAME_NOT_FOUND
;
601 BReference
<NotificationService
> reference(service
);
604 return service
->RemoveListener(eventSpecifier
, listener
);
612 notifications_init(void)
614 status_t status
= NotificationManager::CreateManager();
616 panic("Creating the notification manager failed: %s\n",
622 #endif // _KERNEL_MODE