2 * Copyright 2001-2014 Haiku, Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
6 * Axel Dörfler, axeld@pinc-software.de
7 * Erik Jaesler, erik@cgsoftware.com
11 #include <TokenSpace.h>
17 #include <MessageFilter.h>
18 #include <Messenger.h>
19 #include <PropertyInfo.h>
30 using BPrivate::gDefaultTokens
;
33 static const char* kArchiveNameField
= "_name";
35 static const uint32 kMsgStartObserving
= '_OBS';
36 static const uint32 kMsgStopObserving
= '_OBP';
37 static const char* kObserveTarget
= "be:observe_target";
40 static property_info sHandlerPropInfo
[] = {
43 { B_GET_PROPERTY
}, // commands
44 { B_DIRECT_SPECIFIER
}, // specifiers
48 { // ctypes (compound_type)
71 { B_DIRECT_SPECIFIER
},
80 { B_DIRECT_SPECIFIER
},
90 bool FilterDeleter(void* filter
);
99 status_t
SendNotices(uint32 what
, const BMessage
* notice
);
100 status_t
Add(const BHandler
* handler
, uint32 what
);
101 status_t
Add(const BMessenger
& messenger
, uint32 what
);
102 status_t
Remove(const BHandler
* handler
, uint32 what
);
103 status_t
Remove(const BMessenger
& messenger
, uint32 what
);
107 typedef map
<uint32
, vector
<const BHandler
*> > HandlerObserverMap
;
108 typedef map
<uint32
, vector
<BMessenger
> > MessengerObserverMap
;
110 void _ValidateHandlers(uint32 what
);
111 void _SendNotices(uint32 what
, BMessage
* notice
);
113 HandlerObserverMap fHandlerMap
;
114 MessengerObserverMap fMessengerMap
;
117 } // namespace BPrivate
119 using namespace BPrivate
;
125 BHandler::BHandler(const char* name
)
133 BHandler::~BHandler()
136 BLooper
* looper
= Looper();
137 looper
->RemoveHandler(this);
141 // remove all filters
143 int32 count
= fFilters
->CountItems();
144 for (int32 i
= 0; i
< count
; i
++)
145 delete (BMessageFilter
*)fFilters
->ItemAtFast(i
);
149 // remove all observers (the observer list manages itself)
150 delete fObserverList
;
154 gDefaultTokens
.RemoveToken(fToken
);
158 BHandler::BHandler(BMessage
* data
)
162 const char* name
= NULL
;
165 data
->FindString(kArchiveNameField
, &name
);
172 BHandler::Instantiate(BMessage
* data
)
174 if (!validate_instantiation(data
, "BHandler"))
177 return new BHandler(data
);
182 BHandler::Archive(BMessage
* data
, bool deep
) const
184 status_t status
= BArchivable::Archive(data
, deep
);
191 return data
->AddString(kArchiveNameField
, fName
);
196 BHandler::MessageReceived(BMessage
* message
)
198 BMessage
reply(B_REPLY
);
200 switch (message
->what
) {
201 case kMsgStartObserving
:
202 case kMsgStopObserving
:
206 if (message
->FindMessenger(kObserveTarget
, &target
) != B_OK
207 || message
->FindInt32(B_OBSERVE_WHAT_CHANGE
, (int32
*)&what
)
212 ObserverList
* list
= _ObserverList();
214 if (message
->what
== kMsgStartObserving
)
215 list
->Add(target
, what
);
217 list
->Remove(target
, what
);
229 status_t err
= message
->GetCurrentSpecifier(&cur
, &specifier
,
231 if (err
!= B_OK
&& err
!= B_BAD_SCRIPT_SYNTAX
)
234 // B_BAD_SCRIPT_SYNTAX defaults to the Messenger property
235 if (err
== B_BAD_SCRIPT_SYNTAX
|| cur
< 0
236 || (strcmp(prop
, "Messenger") == 0)) {
237 err
= reply
.AddMessenger("result", this);
239 } else if (strcmp(prop
, "Suites") == 0) {
240 err
= GetSupportedSuites(&reply
);
242 } else if (strcmp(prop
, "InternalName") == 0) {
243 err
= reply
.AddString("result", Name());
248 reply
.AddInt32("error", B_OK
);
249 message
->SendReply(&reply
);
252 // let's try next handler
256 case B_GET_SUPPORTED_SUITES
:
258 reply
.AddInt32("error", GetSupportedSuites(&reply
));
259 message
->SendReply(&reply
);
264 // ToDo: there is some more work needed here
265 // (someone in the know should fill in)!
268 // we need to apply the next handler's filters here, too
269 BHandler
* target
= Looper()->_HandlerFilter(message
, fNextHandler
);
270 if (target
!= NULL
&& target
!= this) {
271 // TODO: we also need to make sure that "target" is not before
272 // us in the handler chain - at least in case it wasn't before
273 // the handler actually targeted with this message - this could
275 target
->MessageReceived(message
);
277 } else if (message
->what
!= B_MESSAGE_NOT_UNDERSTOOD
278 && (message
->WasDropped() || message
->HasSpecifiers())) {
279 printf("BHandler %s: MessageReceived() couldn't understand the message:\n", Name());
280 message
->PrintToStream();
281 message
->SendReply(B_MESSAGE_NOT_UNDERSTOOD
);
287 BHandler::Looper() const
294 BHandler::SetName(const char* name
)
302 fName
= strdup(name
);
307 BHandler::Name() const
314 BHandler::SetNextHandler(BHandler
* handler
)
316 if (fLooper
== NULL
) {
317 debugger("handler must belong to looper before setting NextHandler");
321 if (!fLooper
->IsLocked()) {
322 debugger("The handler's looper must be locked before setting NextHandler");
326 if (handler
!= NULL
&& fLooper
!= handler
->Looper()) {
327 debugger("The handler and its NextHandler must have the same looper");
331 fNextHandler
= handler
;
336 BHandler::NextHandler() const
343 BHandler::AddFilter(BMessageFilter
* filter
)
345 BLooper
* looper
= fLooper
;
346 if (looper
!= NULL
&& !looper
->IsLocked()) {
347 debugger("Owning Looper must be locked before calling SetFilterList");
352 filter
->SetLooper(looper
);
354 if (fFilters
== NULL
)
355 fFilters
= new BList
;
357 fFilters
->AddItem(filter
);
362 BHandler::RemoveFilter(BMessageFilter
* filter
)
364 BLooper
* looper
= fLooper
;
365 if (looper
!= NULL
&& !looper
->IsLocked()) {
366 debugger("Owning Looper must be locked before calling SetFilterList");
370 if (fFilters
!= NULL
&& fFilters
->RemoveItem((void*)filter
)) {
371 filter
->SetLooper(NULL
);
380 BHandler::SetFilterList(BList
* filters
)
382 BLooper
* looper
= fLooper
;
383 if (looper
!= NULL
&& !looper
->IsLocked()) {
384 debugger("Owning Looper must be locked before calling SetFilterList");
389 @note I would like to use BObjectList internally, but this function is
390 spec'd such that fFilters would get deleted and then assigned
391 'filters', which would obviously mess this up. Wondering if
392 anyone ever assigns a list of filters and then checks against
393 FilterList() to see if they are the same.
396 // TODO: Explore issues with using BObjectList
397 if (fFilters
!= NULL
) {
398 fFilters
->DoForEach(FilterDeleter
);
404 for (int32 i
= 0; i
< fFilters
->CountItems(); ++i
) {
405 BMessageFilter
* filter
=
406 static_cast<BMessageFilter
*>(fFilters
->ItemAt(i
));
408 filter
->SetLooper(looper
);
415 BHandler::FilterList()
422 BHandler::LockLooper()
424 BLooper
* looper
= fLooper
;
425 // Locking the looper also makes sure that the looper is valid
426 if (looper
!= NULL
&& looper
->Lock()) {
427 // Have we locked the right looper? That's as far as the
428 // "pseudo-atomic" operation mentioned in the BeBook.
429 if (fLooper
== looper
)
432 // we locked the wrong looper, bail out
441 BHandler::LockLooperWithTimeout(bigtime_t timeout
)
443 BLooper
* looper
= fLooper
;
447 status_t status
= looper
->LockWithTimeout(timeout
);
451 if (fLooper
!= looper
) {
452 // we locked the wrong looper, bail out
454 return B_MISMATCHED_VALUES
;
462 BHandler::UnlockLooper()
469 BHandler::ResolveSpecifier(BMessage
* message
, int32 index
,
470 BMessage
* specifier
, int32 what
, const char* property
)
472 // Straight from the BeBook
473 BPropertyInfo
propertyInfo(sHandlerPropInfo
);
474 if (propertyInfo
.FindMatch(message
, index
, specifier
, what
, property
) >= 0)
477 BMessage
reply(B_MESSAGE_NOT_UNDERSTOOD
);
478 reply
.AddInt32("error", B_BAD_SCRIPT_SYNTAX
);
479 reply
.AddString("message", "Didn't understand the specifier(s)");
480 message
->SendReply(&reply
);
487 BHandler::GetSupportedSuites(BMessage
* data
)
490 @note This is the output from the original implementation (calling
491 PrintToStream() on both data and the contained BPropertyInfo):
493 BMessage: what = (0x0, or 0)
494 entry suites, type='CSTR', c=1, size=21, data[0]: "suite/vnd.Be-handler"
495 entry messages, type='SCTD', c=1, size= 0,
496 property commands types specifiers
497 --------------------------------------------------------------------------------
502 Messenger PGET GNSM 1
503 InternalName PGET RTSC 1
505 With a good deal of trial and error, I determined that the
506 parenthetical clauses are entries in the 'ctypes' field of
507 property_info. 'ctypes' is an array of 'compound_type', which
508 contains an array of 'field_pair's. I haven't the foggiest what
509 either 'compound_type' or 'field_pair' is for, being as the
510 scripting docs are so bloody horrible. The corresponding
511 property_info array is declared in the globals section.
517 status_t result
= data
->AddString("suites", "suite/vnd.Be-handler");
518 if (result
== B_OK
) {
519 BPropertyInfo
propertyInfo(sHandlerPropInfo
);
520 result
= data
->AddFlat("messages", &propertyInfo
);
528 BHandler::StartWatching(BMessenger target
, uint32 what
)
530 BMessage
message(kMsgStartObserving
);
531 message
.AddMessenger(kObserveTarget
, this);
532 message
.AddInt32(B_OBSERVE_WHAT_CHANGE
, what
);
534 return target
.SendMessage(&message
);
539 BHandler::StartWatchingAll(BMessenger target
)
541 return StartWatching(target
, B_OBSERVER_OBSERVE_ALL
);
546 BHandler::StopWatching(BMessenger target
, uint32 what
)
548 BMessage
message(kMsgStopObserving
);
549 message
.AddMessenger(kObserveTarget
, this);
550 message
.AddInt32(B_OBSERVE_WHAT_CHANGE
, what
);
552 return target
.SendMessage(&message
);
557 BHandler::StopWatchingAll(BMessenger target
)
559 return StopWatching(target
, B_OBSERVER_OBSERVE_ALL
);
564 BHandler::StartWatching(BHandler
* handler
, uint32 what
)
566 ObserverList
* list
= _ObserverList();
570 return list
->Add(handler
, what
);
575 BHandler::StartWatchingAll(BHandler
* handler
)
577 return StartWatching(handler
, B_OBSERVER_OBSERVE_ALL
);
582 BHandler::StopWatching(BHandler
* handler
, uint32 what
)
584 ObserverList
* list
= _ObserverList();
588 return list
->Remove(handler
, what
);
593 BHandler::StopWatchingAll(BHandler
* handler
)
595 return StopWatching(handler
, B_OBSERVER_OBSERVE_ALL
);
600 BHandler::Perform(perform_code d
, void* arg
)
602 return BArchivable::Perform(d
, arg
);
607 BHandler::SendNotices(uint32 what
, const BMessage
* notice
)
609 if (fObserverList
!= NULL
)
610 fObserverList
->SendNotices(what
, notice
);
615 BHandler::IsWatched() const
617 return fObserverList
&& !fObserverList
->IsEmpty();
622 BHandler::_InitData(const char* name
)
629 fObserverList
= NULL
;
631 fToken
= gDefaultTokens
.NewToken(B_HANDLER_TOKEN
, this);
636 BHandler::_ObserverList()
638 if (fObserverList
== NULL
)
639 fObserverList
= new (std::nothrow
) BPrivate::ObserverList();
641 return fObserverList
;
645 BHandler::BHandler(const BHandler
&)
647 // No copy construction allowed.
652 BHandler::operator=(const BHandler
&)
654 // No assignments allowed.
660 BHandler::SetLooper(BLooper
* looper
)
663 gDefaultTokens
.SetHandlerTarget(fToken
,
664 looper
? looper
->fDirectTarget
: NULL
);
666 if (fFilters
!= NULL
) {
667 for (int32 i
= 0; i
< fFilters
->CountItems(); i
++) {
668 static_cast<BMessageFilter
*>(
669 fFilters
->ItemAtFast(i
))->SetLooper(looper
);
676 // binary compatibility with R4.5
679 _ReservedHandler1__8BHandler(BHandler
* handler
, uint32 what
,
680 const BMessage
* notice
)
682 handler
->BHandler::SendNotices(what
, notice
);
687 void BHandler::_ReservedHandler2() {}
688 void BHandler::_ReservedHandler3() {}
689 void BHandler::_ReservedHandler4() {}
695 ObserverList::ObserverList()
700 ObserverList::~ObserverList()
706 ObserverList::_ValidateHandlers(uint32 what
)
708 vector
<const BHandler
*>& handlers
= fHandlerMap
[what
];
709 vector
<const BHandler
*>::iterator iterator
= handlers
.begin();
711 while (iterator
!= handlers
.end()) {
712 BMessenger
target(*iterator
);
713 if (!target
.IsValid()) {
719 iterator
= handlers
.erase(iterator
);
725 ObserverList::_SendNotices(uint32 what
, BMessage
* notice
)
727 // first iterate over the list of handlers and try to make valid
728 // messengers out of them
729 _ValidateHandlers(what
);
731 // now send it to all messengers we know
732 vector
<BMessenger
>& messengers
= fMessengerMap
[what
];
733 vector
<BMessenger
>::iterator iterator
= messengers
.begin();
735 while (iterator
!= messengers
.end()) {
736 if (!(*iterator
).IsValid()) {
737 iterator
= messengers
.erase(iterator
);
741 (*iterator
).SendMessage(notice
);
748 ObserverList::SendNotices(uint32 what
, const BMessage
* notice
)
750 BMessage
* copy
= NULL
;
751 if (notice
!= NULL
) {
752 copy
= new BMessage(*notice
);
753 copy
->what
= B_OBSERVER_NOTICE_CHANGE
;
754 copy
->AddInt32(B_OBSERVE_ORIGINAL_WHAT
, notice
->what
);
756 copy
= new BMessage(B_OBSERVER_NOTICE_CHANGE
);
758 copy
->AddInt32(B_OBSERVE_WHAT_CHANGE
, what
);
760 _SendNotices(what
, copy
);
761 _SendNotices(B_OBSERVER_OBSERVE_ALL
, copy
);
770 ObserverList::Add(const BHandler
* handler
, uint32 what
)
773 return B_BAD_HANDLER
;
775 // if this handler already represents a valid target, add its messenger
776 BMessenger
target(handler
);
777 if (target
.IsValid())
778 return Add(target
, what
);
780 vector
<const BHandler
*> &handlers
= fHandlerMap
[what
];
782 vector
<const BHandler
*>::iterator iter
;
783 iter
= find(handlers
.begin(), handlers
.end(), handler
);
784 if (iter
!= handlers
.end()) {
785 // TODO: do we want to have a reference count for this?
789 handlers
.push_back(handler
);
795 ObserverList::Add(const BMessenger
&messenger
, uint32 what
)
797 vector
<BMessenger
> &messengers
= fMessengerMap
[what
];
799 vector
<BMessenger
>::iterator iter
;
800 iter
= find(messengers
.begin(), messengers
.end(), messenger
);
801 if (iter
!= messengers
.end()) {
802 // TODO: do we want to have a reference count for this?
806 messengers
.push_back(messenger
);
812 ObserverList::Remove(const BHandler
* handler
, uint32 what
)
815 return B_BAD_HANDLER
;
817 // look into the list of messengers
818 BMessenger
target(handler
);
819 if (target
.IsValid() && Remove(target
, what
) == B_OK
)
822 vector
<const BHandler
*> &handlers
= fHandlerMap
[what
];
824 vector
<const BHandler
*>::iterator iterator
= find(handlers
.begin(),
825 handlers
.end(), handler
);
826 if (iterator
!= handlers
.end()) {
827 handlers
.erase(iterator
);
828 if (handlers
.empty())
829 fHandlerMap
.erase(what
);
834 return B_BAD_HANDLER
;
839 ObserverList::Remove(const BMessenger
&messenger
, uint32 what
)
841 vector
<BMessenger
> &messengers
= fMessengerMap
[what
];
843 vector
<BMessenger
>::iterator iterator
= find(messengers
.begin(),
844 messengers
.end(), messenger
);
845 if (iterator
!= messengers
.end()) {
846 messengers
.erase(iterator
);
847 if (messengers
.empty())
848 fMessengerMap
.erase(what
);
853 return B_BAD_HANDLER
;
858 ObserverList::IsEmpty()
860 return fHandlerMap
.empty() && fMessengerMap
.empty();
868 FilterDeleter(void* _filter
)
870 delete static_cast<BMessageFilter
*>(_filter
);