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
},
89 bool FilterDeleter(void* filter
);
98 status_t
SendNotices(uint32 what
, const BMessage
* notice
);
99 status_t
Add(const BHandler
* handler
, uint32 what
);
100 status_t
Add(const BMessenger
& messenger
, uint32 what
);
101 status_t
Remove(const BHandler
* handler
, uint32 what
);
102 status_t
Remove(const BMessenger
& messenger
, uint32 what
);
106 typedef map
<uint32
, vector
<const BHandler
*> > HandlerObserverMap
;
107 typedef map
<uint32
, vector
<BMessenger
> > MessengerObserverMap
;
109 void _ValidateHandlers(uint32 what
);
110 void _SendNotices(uint32 what
, BMessage
* notice
);
112 HandlerObserverMap fHandlerMap
;
113 MessengerObserverMap fMessengerMap
;
116 } // namespace BPrivate
118 using namespace BPrivate
;
124 BHandler::BHandler(const char* name
)
132 BHandler::~BHandler()
135 BLooper
* looper
= Looper();
136 looper
->RemoveHandler(this);
140 // remove all filters
142 int32 count
= fFilters
->CountItems();
143 for (int32 i
= 0; i
< count
; i
++)
144 delete (BMessageFilter
*)fFilters
->ItemAtFast(i
);
148 // remove all observers (the observer list manages itself)
149 delete fObserverList
;
153 gDefaultTokens
.RemoveToken(fToken
);
157 BHandler::BHandler(BMessage
* data
)
161 const char* name
= NULL
;
164 data
->FindString(kArchiveNameField
, &name
);
171 BHandler::Instantiate(BMessage
* data
)
173 if (!validate_instantiation(data
, "BHandler"))
176 return new BHandler(data
);
181 BHandler::Archive(BMessage
* data
, bool deep
) const
183 status_t status
= BArchivable::Archive(data
, deep
);
190 return data
->AddString(kArchiveNameField
, fName
);
195 BHandler::MessageReceived(BMessage
* message
)
197 BMessage
reply(B_REPLY
);
199 switch (message
->what
) {
200 case kMsgStartObserving
:
201 case kMsgStopObserving
:
205 if (message
->FindMessenger(kObserveTarget
, &target
) != B_OK
206 || message
->FindInt32(B_OBSERVE_WHAT_CHANGE
, (int32
*)&what
)
211 ObserverList
* list
= _ObserverList();
213 if (message
->what
== kMsgStartObserving
)
214 list
->Add(target
, what
);
216 list
->Remove(target
, what
);
228 status_t err
= message
->GetCurrentSpecifier(&cur
, &specifier
,
230 if (err
!= B_OK
&& err
!= B_BAD_SCRIPT_SYNTAX
)
233 // B_BAD_SCRIPT_SYNTAX defaults to the Messenger property
234 if (err
== B_BAD_SCRIPT_SYNTAX
|| cur
< 0
235 || (strcmp(prop
, "Messenger") == 0)) {
236 err
= reply
.AddMessenger("result", this);
238 } else if (strcmp(prop
, "Suites") == 0) {
239 err
= GetSupportedSuites(&reply
);
241 } else if (strcmp(prop
, "InternalName") == 0) {
242 err
= reply
.AddString("result", Name());
247 reply
.AddInt32("error", B_OK
);
248 message
->SendReply(&reply
);
251 // let's try next handler
255 case B_GET_SUPPORTED_SUITES
:
257 reply
.AddInt32("error", GetSupportedSuites(&reply
));
258 message
->SendReply(&reply
);
263 // ToDo: there is some more work needed here
264 // (someone in the know should fill in)!
267 // we need to apply the next handler's filters here, too
268 BHandler
* target
= Looper()->_HandlerFilter(message
, fNextHandler
);
269 if (target
!= NULL
&& target
!= this) {
270 // TODO: we also need to make sure that "target" is not before
271 // us in the handler chain - at least in case it wasn't before
272 // the handler actually targeted with this message - this could
274 target
->MessageReceived(message
);
276 } else if (message
->what
!= B_MESSAGE_NOT_UNDERSTOOD
277 && (message
->WasDropped() || message
->HasSpecifiers())) {
278 printf("BHandler %s: MessageReceived() couldn't understand the message:\n", Name());
279 message
->PrintToStream();
280 message
->SendReply(B_MESSAGE_NOT_UNDERSTOOD
);
286 BHandler::Looper() const
293 BHandler::SetName(const char* name
)
301 fName
= strdup(name
);
306 BHandler::Name() const
313 BHandler::SetNextHandler(BHandler
* handler
)
315 if (fLooper
== NULL
) {
316 debugger("handler must belong to looper before setting NextHandler");
320 if (!fLooper
->IsLocked()) {
321 debugger("The handler's looper must be locked before setting NextHandler");
325 if (handler
!= NULL
&& fLooper
!= handler
->Looper()) {
326 debugger("The handler and its NextHandler must have the same looper");
330 fNextHandler
= handler
;
335 BHandler::NextHandler() const
342 BHandler::AddFilter(BMessageFilter
* filter
)
344 BLooper
* looper
= fLooper
;
345 if (looper
!= NULL
&& !looper
->IsLocked()) {
346 debugger("Owning Looper must be locked before calling SetFilterList");
351 filter
->SetLooper(looper
);
353 if (fFilters
== NULL
)
354 fFilters
= new BList
;
356 fFilters
->AddItem(filter
);
361 BHandler::RemoveFilter(BMessageFilter
* filter
)
363 BLooper
* looper
= fLooper
;
364 if (looper
!= NULL
&& !looper
->IsLocked()) {
365 debugger("Owning Looper must be locked before calling SetFilterList");
369 if (fFilters
!= NULL
&& fFilters
->RemoveItem((void*)filter
)) {
370 filter
->SetLooper(NULL
);
379 BHandler::SetFilterList(BList
* filters
)
381 BLooper
* looper
= fLooper
;
382 if (looper
!= NULL
&& !looper
->IsLocked()) {
383 debugger("Owning Looper must be locked before calling SetFilterList");
388 @note I would like to use BObjectList internally, but this function is
389 spec'd such that fFilters would get deleted and then assigned
390 'filters', which would obviously mess this up. Wondering if
391 anyone ever assigns a list of filters and then checks against
392 FilterList() to see if they are the same.
395 // TODO: Explore issues with using BObjectList
396 if (fFilters
!= NULL
) {
397 fFilters
->DoForEach(FilterDeleter
);
403 for (int32 i
= 0; i
< fFilters
->CountItems(); ++i
) {
404 BMessageFilter
* filter
=
405 static_cast<BMessageFilter
*>(fFilters
->ItemAt(i
));
407 filter
->SetLooper(looper
);
414 BHandler::FilterList()
421 BHandler::LockLooper()
423 BLooper
* looper
= fLooper
;
424 // Locking the looper also makes sure that the looper is valid
425 if (looper
!= NULL
&& looper
->Lock()) {
426 // Have we locked the right looper? That's as far as the
427 // "pseudo-atomic" operation mentioned in the BeBook.
428 if (fLooper
== looper
)
431 // we locked the wrong looper, bail out
440 BHandler::LockLooperWithTimeout(bigtime_t timeout
)
442 BLooper
* looper
= fLooper
;
446 status_t status
= looper
->LockWithTimeout(timeout
);
450 if (fLooper
!= looper
) {
451 // we locked the wrong looper, bail out
453 return B_MISMATCHED_VALUES
;
461 BHandler::UnlockLooper()
468 BHandler::ResolveSpecifier(BMessage
* message
, int32 index
,
469 BMessage
* specifier
, int32 what
, const char* property
)
471 // Straight from the BeBook
472 BPropertyInfo
propertyInfo(sHandlerPropInfo
);
473 if (propertyInfo
.FindMatch(message
, index
, specifier
, what
, property
) >= 0)
476 BMessage
reply(B_MESSAGE_NOT_UNDERSTOOD
);
477 reply
.AddInt32("error", B_BAD_SCRIPT_SYNTAX
);
478 reply
.AddString("message", "Didn't understand the specifier(s)");
479 message
->SendReply(&reply
);
486 BHandler::GetSupportedSuites(BMessage
* data
)
489 @note This is the output from the original implementation (calling
490 PrintToStream() on both data and the contained BPropertyInfo):
492 BMessage: what = (0x0, or 0)
493 entry suites, type='CSTR', c=1, size=21, data[0]: "suite/vnd.Be-handler"
494 entry messages, type='SCTD', c=1, size= 0,
495 property commands types specifiers
496 --------------------------------------------------------------------------------
501 Messenger PGET GNSM 1
502 InternalName PGET RTSC 1
504 With a good deal of trial and error, I determined that the
505 parenthetical clauses are entries in the 'ctypes' field of
506 property_info. 'ctypes' is an array of 'compound_type', which
507 contains an array of 'field_pair's. I haven't the foggiest what
508 either 'compound_type' or 'field_pair' is for, being as the
509 scripting docs are so bloody horrible. The corresponding
510 property_info array is declared in the globals section.
516 status_t result
= data
->AddString("suites", "suite/vnd.Be-handler");
517 if (result
== B_OK
) {
518 BPropertyInfo
propertyInfo(sHandlerPropInfo
);
519 result
= data
->AddFlat("messages", &propertyInfo
);
527 BHandler::StartWatching(BMessenger target
, uint32 what
)
529 BMessage
message(kMsgStartObserving
);
530 message
.AddMessenger(kObserveTarget
, this);
531 message
.AddInt32(B_OBSERVE_WHAT_CHANGE
, what
);
533 return target
.SendMessage(&message
);
538 BHandler::StartWatchingAll(BMessenger target
)
540 return StartWatching(target
, B_OBSERVER_OBSERVE_ALL
);
545 BHandler::StopWatching(BMessenger target
, uint32 what
)
547 BMessage
message(kMsgStopObserving
);
548 message
.AddMessenger(kObserveTarget
, this);
549 message
.AddInt32(B_OBSERVE_WHAT_CHANGE
, what
);
551 return target
.SendMessage(&message
);
556 BHandler::StopWatchingAll(BMessenger target
)
558 return StopWatching(target
, B_OBSERVER_OBSERVE_ALL
);
563 BHandler::StartWatching(BHandler
* handler
, uint32 what
)
565 ObserverList
* list
= _ObserverList();
569 return list
->Add(handler
, what
);
574 BHandler::StartWatchingAll(BHandler
* handler
)
576 return StartWatching(handler
, B_OBSERVER_OBSERVE_ALL
);
581 BHandler::StopWatching(BHandler
* handler
, uint32 what
)
583 ObserverList
* list
= _ObserverList();
587 return list
->Remove(handler
, what
);
592 BHandler::StopWatchingAll(BHandler
* handler
)
594 return StopWatching(handler
, B_OBSERVER_OBSERVE_ALL
);
599 BHandler::Perform(perform_code d
, void* arg
)
601 return BArchivable::Perform(d
, arg
);
606 BHandler::SendNotices(uint32 what
, const BMessage
* notice
)
608 if (fObserverList
!= NULL
)
609 fObserverList
->SendNotices(what
, notice
);
614 BHandler::IsWatched() const
616 return fObserverList
&& !fObserverList
->IsEmpty();
621 BHandler::_InitData(const char* name
)
628 fObserverList
= NULL
;
630 fToken
= gDefaultTokens
.NewToken(B_HANDLER_TOKEN
, this);
635 BHandler::_ObserverList()
637 if (fObserverList
== NULL
)
638 fObserverList
= new (std::nothrow
) BPrivate::ObserverList();
640 return fObserverList
;
644 BHandler::BHandler(const BHandler
&)
646 // No copy construction allowed.
651 BHandler::operator=(const BHandler
&)
653 // No assignments allowed.
659 BHandler::SetLooper(BLooper
* looper
)
662 gDefaultTokens
.SetHandlerTarget(fToken
,
663 looper
? looper
->fDirectTarget
: NULL
);
665 if (fFilters
!= NULL
) {
666 for (int32 i
= 0; i
< fFilters
->CountItems(); i
++) {
667 static_cast<BMessageFilter
*>(
668 fFilters
->ItemAtFast(i
))->SetLooper(looper
);
675 // binary compatibility with R4.5
678 _ReservedHandler1__8BHandler(BHandler
* handler
, uint32 what
,
679 const BMessage
* notice
)
681 handler
->BHandler::SendNotices(what
, notice
);
686 void BHandler::_ReservedHandler2() {}
687 void BHandler::_ReservedHandler3() {}
688 void BHandler::_ReservedHandler4() {}
694 ObserverList::ObserverList()
699 ObserverList::~ObserverList()
705 ObserverList::_ValidateHandlers(uint32 what
)
707 vector
<const BHandler
*>& handlers
= fHandlerMap
[what
];
708 vector
<const BHandler
*>::iterator iterator
= handlers
.begin();
710 while (iterator
!= handlers
.end()) {
711 BMessenger
target(*iterator
);
712 if (!target
.IsValid()) {
718 iterator
= handlers
.erase(iterator
);
724 ObserverList::_SendNotices(uint32 what
, BMessage
* notice
)
726 // first iterate over the list of handlers and try to make valid
727 // messengers out of them
728 _ValidateHandlers(what
);
730 // now send it to all messengers we know
731 vector
<BMessenger
>& messengers
= fMessengerMap
[what
];
732 vector
<BMessenger
>::iterator iterator
= messengers
.begin();
734 while (iterator
!= messengers
.end()) {
735 if (!(*iterator
).IsValid()) {
736 iterator
= messengers
.erase(iterator
);
740 (*iterator
).SendMessage(notice
);
747 ObserverList::SendNotices(uint32 what
, const BMessage
* notice
)
749 BMessage
* copy
= NULL
;
750 if (notice
!= NULL
) {
751 copy
= new BMessage(*notice
);
752 copy
->what
= B_OBSERVER_NOTICE_CHANGE
;
753 copy
->AddInt32(B_OBSERVE_ORIGINAL_WHAT
, notice
->what
);
755 copy
= new BMessage(B_OBSERVER_NOTICE_CHANGE
);
757 copy
->AddInt32(B_OBSERVE_WHAT_CHANGE
, what
);
759 _SendNotices(what
, copy
);
760 _SendNotices(B_OBSERVER_OBSERVE_ALL
, copy
);
769 ObserverList::Add(const BHandler
* handler
, uint32 what
)
772 return B_BAD_HANDLER
;
774 // if this handler already represents a valid target, add its messenger
775 BMessenger
target(handler
);
776 if (target
.IsValid())
777 return Add(target
, what
);
779 vector
<const BHandler
*> &handlers
= fHandlerMap
[what
];
781 vector
<const BHandler
*>::iterator iter
;
782 iter
= find(handlers
.begin(), handlers
.end(), handler
);
783 if (iter
!= handlers
.end()) {
784 // TODO: do we want to have a reference count for this?
788 handlers
.push_back(handler
);
794 ObserverList::Add(const BMessenger
&messenger
, uint32 what
)
796 vector
<BMessenger
> &messengers
= fMessengerMap
[what
];
798 vector
<BMessenger
>::iterator iter
;
799 iter
= find(messengers
.begin(), messengers
.end(), messenger
);
800 if (iter
!= messengers
.end()) {
801 // TODO: do we want to have a reference count for this?
805 messengers
.push_back(messenger
);
811 ObserverList::Remove(const BHandler
* handler
, uint32 what
)
814 return B_BAD_HANDLER
;
816 // look into the list of messengers
817 BMessenger
target(handler
);
818 if (target
.IsValid() && Remove(target
, what
) == B_OK
)
821 vector
<const BHandler
*> &handlers
= fHandlerMap
[what
];
823 vector
<const BHandler
*>::iterator iterator
= find(handlers
.begin(),
824 handlers
.end(), handler
);
825 if (iterator
!= handlers
.end()) {
826 handlers
.erase(iterator
);
827 if (handlers
.empty())
828 fHandlerMap
.erase(what
);
833 return B_BAD_HANDLER
;
838 ObserverList::Remove(const BMessenger
&messenger
, uint32 what
)
840 vector
<BMessenger
> &messengers
= fMessengerMap
[what
];
842 vector
<BMessenger
>::iterator iterator
= find(messengers
.begin(),
843 messengers
.end(), messenger
);
844 if (iterator
!= messengers
.end()) {
845 messengers
.erase(iterator
);
846 if (messengers
.empty())
847 fMessengerMap
.erase(what
);
852 return B_BAD_HANDLER
;
857 ObserverList::IsEmpty()
859 return fHandlerMap
.empty() && fMessengerMap
.empty();
867 FilterDeleter(void* _filter
)
869 delete static_cast<BMessageFilter
*>(_filter
);