1 //------------------------------------------------------------------------------ 2 // Copyright (c) 2001-2002, OpenBeOS 3 // 4 // Permission is hereby granted, free of charge, to any person obtaining a 5 // copy of this software and associated documentation files (the "Software"), 6 // to deal in the Software without restriction, including without limitation 7 // the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 // and/or sell copies of the Software, and to permit persons to whom the 9 // Software is furnished to do so, subject to the following conditions: 10 // 11 // The above copyright notice and this permission notice shall be included in 12 // all copies or substantial portions of the Software. 13 // 14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 // DEALINGS IN THE SOFTWARE. 21 // 22 // File Name: Handler.cpp 23 // Author: Erik Jaesler (erik@cgsoftware.com) 24 // Description: BHandler defines the message-handling protocol. 25 // MessageReceived() is its lynchpin. 26 //------------------------------------------------------------------------------ 27 /** 28 @note Some musings on the member variable 'fToken'. In searching a dump 29 of libbe.so, I found a struct/class called 'TokenSpace', which has 30 various member functions like 'new_token'. More intriguing is a 31 dump of Dano's version of libbe.so: there is BPrivate::BTokenSpace, 32 which also has functions like 'NewToken'. There's more: one 33 version of BTokenSpace::NewToken takes a pointer to another new 34 class, BPrivate::BDirectMessageTarget. Only a constructor, 35 destructor and vtable are listed for it, so I'm guessing it's an 36 abstract base class (or not very useful ;). My guess is that 37 BDirectMessageTarget facilitates sending messages straight to an 38 associated BHandler. Maybe from app_server? Probably not, since 39 you'd have to do IPC anyway. But maybe within the same team, or 40 even between teams? It might save unnecessary trips to and from 41 app_server for messages which otherwise are entirely client-side. 42 43 Back to tokens. There are also these functions in R5: 44 _safe_get_server_token_(const BLooper*, int32*) 45 BWindow::find_token_and_handler(BMessage*, int32*, BHandler**) 46 BWindow::get_server_token 47 48 and Dano adds a few more provocative sounding functions: 49 get_handler_token(short, void*) (listed 3 times, actually) 50 new_handler_token(short, void*) 51 remove_handler_token(short, void*) 52 53 Taken all together, I think there's a sound argument to be made that 54 each BHandler has an int32 token associated with it in app_server. 55 56 Furthermore, there is, in R5, a function set_token_type(long, short) 57 which leads me to think that although BHandler's have server tokens 58 associated with them, the tokening facility is, in fact, generic. 59 These functions would seem to support that theory: 60 BBitmap::get_server_token 61 BPicture::set_token 62 63 An important question is whether tokens are generated on the client 64 side and registered with the server or generated on the server and 65 given back to the client. The exported functions of TokenSpace in 66 libbe's dump are: 67 ~TokenSpace 68 TokenSpace 69 adjust_free(long, long) 70 dump() 71 find_free_entry(long*, long*) 72 full_search_adjust() 73 get_token(void**) 74 get_token(short*, void**) 75 new_token(long, short, void*) 76 new_token_array(long) 77 remove_token(long) 78 set_token_type(long, short) 79 80 TokenSpace functions are also exported from app_server: 81 ~TokenSpace 82 TokenSpace 83 adjust_free(long, long) 84 cleanup_dead(long) 85 delete_atom(SAtom*) 86 dump_tokens() 87 find_free_entry(long*, long*) 88 full_search_adjust() 89 get_token(long, void**) 90 get_token(long, short*, void**) 91 get_token_by_type(int*, short, long, void**) 92 grab_atom(long, SAtom**) 93 iterate_tokens(long, short, 94 unsigned long(*)(long, long, short, void*, void*), 95 void*) 96 new_token(long, short, void*) 97 new_token_array(long) 98 remove_token(long) 99 set_token_type(long, short) 100 101 While there are common functions in both locations, the fact that 102 app_server exports TokenSpace functions which libbe.so does not 103 leads me to believe that libbe.so and app_server each have their own 104 versions of TokenSpace. While it's possible that the libbe version 105 simply acts as a proxy for the app_server version, it seems not 106 only inefficient but unnecessary as well: client-side objects 107 exists in a different "namespace" than server-side objects, so over- 108 lap between the two token sets shouldn't be an issue. 109 110 Obviously, I can't be entirely sure this is how R5 does it, but it 111 seems like a reasonable design to follow for our purposes. 112 */ 113 /** 114 @note Thought on "pseudo-atomic" operations in Lock(), LockWithTimeout(), 115 and Unlock(). Seems like avoiding the possibility of a looper 116 change during these functions would be the way to go, and having a 117 semaphore that protects SetLooper() would do the job very nicely. 118 Maybe that's too heavy-weight a solution, though. 119 */ 120 121 // Standard Includes ----------------------------------------------------------- 122 #include <algorithm> 123 #include <stdlib.h> 124 #include <string.h> 125 #include <map> 126 #include <vector> 127 128 // System Includes ------------------------------------------------------------- 129 #include <AppDefs.h> 130 #include <Handler.h> 131 #include <Looper.h> 132 #include <Message.h> 133 #include <MessageFilter.h> 134 #include <Messenger.h> 135 #include <PropertyInfo.h> 136 137 // Project Includes ------------------------------------------------------------ 138 #include <TokenSpace.h> 139 140 // Local Includes -------------------------------------------------------------- 141 142 // Local Defines --------------------------------------------------------------- 143 144 // Globals --------------------------------------------------------------------- 145 146 using std::map; 147 using std::vector; 148 using BPrivate::gDefaultTokens; 149 150 const char* gArchiveNameField = "_name"; 151 static property_info gHandlerPropInfo[] = 152 { 153 { 154 // name 155 "Suites", 156 // commands 157 { B_GET_PROPERTY }, 158 // specifiers 159 { B_DIRECT_SPECIFIER }, 160 // usage 161 NULL, 162 // extra data 163 0, 164 // types 165 { }, 166 // ctypes (compound_type) 167 { 168 // ctypes[0] 169 { 170 // pairs[0] 171 { 172 { 173 // name 174 "suites", 175 // type 176 B_STRING_TYPE 177 } 178 } 179 }, 180 // ctypes[1] 181 { 182 // pairs[1] 183 { 184 { 185 // name 186 "messages", 187 // type 188 B_PROPERTY_INFO_TYPE 189 } 190 } 191 } 192 }, 193 // reserved 194 {} 195 }, 196 { 197 "Messenger", 198 { B_GET_PROPERTY }, 199 { B_DIRECT_SPECIFIER }, 200 NULL, 0, 201 { B_MESSENGER_TYPE }, 202 {}, 203 {} 204 }, 205 { 206 "InternalName", 207 { B_GET_PROPERTY }, 208 { B_DIRECT_SPECIFIER }, 209 NULL, 0, 210 { B_STRING_TYPE }, 211 {}, 212 {} 213 }, 214 {} 215 }; 216 217 bool FilterDeleter(void* filter); 218 219 typedef map<unsigned long, vector<BHandler*> > THandlerObserverMap; 220 typedef map<unsigned long, vector<BMessenger> > TMessengerObserverMap; 221 //------------------------------------------------------------------------------ 222 // TODO: Change to BPrivate::BObserverList if possible 223 class _ObserverList 224 { 225 public: 226 _ObserverList(void); 227 ~_ObserverList(void); 228 status_t SendNotices(unsigned long, BMessage const *); 229 status_t StartObserving(BHandler *, unsigned long); 230 status_t StartObserving(const BMessenger&, unsigned long); 231 status_t StopObserving(BHandler *, unsigned long); 232 status_t StopObserving(const BMessenger&, unsigned long); 233 bool IsEmpty(); 234 235 private: 236 THandlerObserverMap fHandlerMap; 237 TMessengerObserverMap fMessengerMap; 238 }; 239 //------------------------------------------------------------------------------ 240 241 242 //------------------------------------------------------------------------------ 243 BHandler::BHandler(const char* name) 244 : BArchivable(), fName(NULL) 245 { 246 InitData(name); 247 } 248 //------------------------------------------------------------------------------ 249 BHandler::~BHandler() 250 { 251 if (fName) 252 { 253 free(fName); 254 } 255 256 gDefaultTokens.RemoveToken(fToken); 257 } 258 //------------------------------------------------------------------------------ 259 BHandler::BHandler(BMessage* data) 260 : BArchivable(data), fName(NULL) 261 { 262 const char* name = NULL; 263 264 if (data) 265 { 266 data->FindString(gArchiveNameField, &name); 267 } 268 269 InitData(name); 270 } 271 //------------------------------------------------------------------------------ 272 BArchivable* BHandler::Instantiate(BMessage* data) 273 { 274 if (!validate_instantiation(data, "BHandler")) 275 { 276 return NULL; 277 } 278 279 return new BHandler(data); 280 } 281 //------------------------------------------------------------------------------ 282 status_t BHandler::Archive(BMessage* data, bool deep) const 283 { 284 status_t err = BArchivable::Archive(data, deep); 285 if (!err) 286 { 287 err = data->AddString(gArchiveNameField, fName); 288 } 289 290 return err; 291 } 292 //------------------------------------------------------------------------------ 293 void BHandler::MessageReceived(BMessage* message) 294 { 295 switch (message->what) 296 { 297 case B_GET_PROPERTY: 298 { 299 BMessage Specifier; 300 int32 form; 301 const char* prop; 302 int32 cur; 303 status_t err; 304 305 err = message->GetCurrentSpecifier(&cur, &Specifier, &form, &prop); 306 if (!err) 307 { 308 BMessage Reply(B_REPLY); 309 if (strcmp(prop, "Suites") == 0) 310 { 311 if (GetSupportedSuites(&Reply) == B_OK && 312 Reply.AddInt32("error", B_OK) == B_OK) 313 { 314 message->SendReply(&Reply); 315 } 316 } 317 else if (strcmp(prop, "Messenger") == 0) 318 { 319 if (Reply.AddMessenger("result", this) == B_OK && 320 Reply.AddInt32("error", B_OK) == B_OK) 321 322 { 323 message->SendReply(&Reply); 324 } 325 } 326 else if (strcmp(prop, "InternalName") == 0) 327 { 328 if (Reply.AddString("result", Name()) == B_OK && 329 Reply.AddInt32("error", B_OK) == B_OK) 330 331 { 332 message->SendReply(&Reply); 333 } 334 } 335 else 336 { 337 // Should never be here 338 debugger("We are *not* supposed to be here"); 339 } 340 } 341 break; 342 } 343 344 default: 345 if (fNextHandler) 346 { 347 fNextHandler->MessageReceived(message); 348 } 349 else 350 { 351 message->SendReply(B_MESSAGE_NOT_UNDERSTOOD); 352 } 353 break; 354 } 355 } 356 //------------------------------------------------------------------------------ 357 BLooper* BHandler::Looper() const 358 { 359 return fLooper; 360 } 361 //------------------------------------------------------------------------------ 362 void BHandler::SetName(const char* name) 363 { 364 if (fName) 365 { 366 free(fName); 367 fName = NULL; 368 } 369 370 if (name) 371 { 372 fName = strdup(name); 373 } 374 } 375 //------------------------------------------------------------------------------ 376 const char* BHandler::Name() const 377 { 378 return fName; 379 } 380 //------------------------------------------------------------------------------ 381 void BHandler::SetNextHandler(BHandler* handler) 382 { 383 if (!fLooper) 384 { 385 debugger("handler must belong to looper before setting NextHandler"); 386 fNextHandler = NULL; 387 return; 388 } 389 390 if (!fLooper->IsLocked()) 391 { 392 debugger("The handler's looper must be locked before setting NextHandler"); 393 return; 394 } 395 396 if (handler && fLooper != handler->Looper()) 397 { 398 debugger("The handler and its NextHandler must have the same looper"); 399 return; 400 } 401 402 // NOTE: I'm sure some sort of threading protection should happen here, 403 // hopefully the spec-mandated BLooper lock is sufficient. 404 // TODO: implement correctly 405 fNextHandler = handler; 406 } 407 //------------------------------------------------------------------------------ 408 BHandler* BHandler::NextHandler() const 409 { 410 return fNextHandler; 411 } 412 //------------------------------------------------------------------------------ 413 void BHandler::AddFilter(BMessageFilter* filter) 414 { 415 // NOTE: Although the documentation states that the handler must belong to 416 // a looper and the looper must be locked in order to use this method, 417 // testing shows that this is not the case in the original implementation. 418 // We may want to investigate enforcing these rules; it would be interesting 419 // to see how many apps out there have violated the dictates of the docs. 420 // For now, though, we'll play nicely. 421 #if 0 422 if (!fLooper) 423 { 424 // TODO: error handling 425 return false; 426 } 427 428 if (!fLooper->IsLocked()) 429 { 430 // TODO: error handling 431 return false; 432 } 433 #endif 434 435 if (!fFilters) 436 { 437 fFilters = new BList; 438 } 439 440 fFilters->AddItem(filter); 441 } 442 //------------------------------------------------------------------------------ 443 bool BHandler::RemoveFilter(BMessageFilter* filter) 444 { 445 // NOTE: Although the documentation states that the handler must belong to 446 // a looper and the looper must be locked in order to use this method, 447 // testing shows that this is not the case in the original implementation. 448 // We may want to investigate enforcing these rules; it would be interesting 449 // to see how many apps out there have violated the dictates of the docs. 450 // For now, though, we'll play nicely. 451 #if 0 452 if (!fLooper) 453 { 454 // TODO: error handling 455 return false; 456 } 457 458 if (!fLooper->IsLocked()) 459 { 460 // TODO: error handling 461 return false; 462 } 463 #endif 464 465 if (fFilters) 466 { 467 if (fFilters->RemoveItem((void*)filter)) 468 { 469 filter->SetLooper(NULL); 470 return true; 471 } 472 } 473 474 return false; 475 } 476 //------------------------------------------------------------------------------ 477 void BHandler::SetFilterList(BList* filters) 478 { 479 /** 480 @note Although the documentation states that the handler must belong to 481 a looper and the looper must be locked in order to use this method, 482 testing shows that this is not the case in the original implementation. 483 */ 484 #if 0 485 if (!fLooper) 486 { 487 // TODO: error handling 488 return; 489 } 490 #endif 491 492 if (fLooper && !fLooper->IsLocked()) 493 { 494 debugger("Owning Looper must be locked before calling SetFilterList"); 495 return; 496 } 497 498 /** 499 @note I would like to use BObjectList internally, but this function is 500 spec'd such that fFilters would get deleted and then assigned 501 'filters', which would obviously mess this up. Wondering if 502 anyone ever assigns a list of filters and then checks against 503 FilterList() to see if they are the same. 504 */ 505 // TODO: Explore issues with using BObjectList 506 if (fFilters) 507 { 508 fFilters->DoForEach(FilterDeleter); 509 delete fFilters; 510 } 511 512 fFilters = filters; 513 if (fFilters) 514 { 515 for (int32 i = 0; i < fFilters->CountItems(); ++i) 516 { 517 BMessageFilter* Filter = 518 static_cast<BMessageFilter*>(fFilters->ItemAt(i)); 519 if (Filter) 520 { 521 Filter->SetLooper(fLooper); 522 } 523 } 524 } 525 } 526 //------------------------------------------------------------------------------ 527 BList* BHandler::FilterList() 528 { 529 return fFilters; 530 } 531 //------------------------------------------------------------------------------ 532 bool BHandler::LockLooper() 533 { 534 /** 535 @note BeBook says that this function "retrieves the handler's looper and 536 unlocks it in a pseudo-atomic operation, thus avoiding a race 537 condition." How "pseudo-atomic" would look completely escapes me, 538 so we'll go with the dumb version for now. Maybe I should use a 539 benaphore? 540 541 BeBook mentions handling the case where the handler's looper 542 changes during this call. I've attempted a "pseudo-atomic" 543 operation to check that. 544 */ 545 BLooper* Looper = fLooper; 546 if (Looper) 547 { 548 bool result = Looper->Lock(); 549 550 // Are we still assigned to the same looper? 551 if (fLooper == Looper) 552 { 553 return result; 554 } 555 else if (result) 556 { 557 // Our looper is different, and the lock was successful on the old 558 // one; undo the lock 559 Looper->Unlock(); 560 } 561 } 562 563 return false; 564 } 565 //------------------------------------------------------------------------------ 566 status_t BHandler::LockLooperWithTimeout(bigtime_t timeout) 567 { 568 /** 569 @note BeBook says that this function "retrieves the handler's looper and 570 unlocks it in a pseudo-atomic operation, thus avoiding a race 571 condition." How "pseudo-atomic" would look completely escapes me, 572 so we'll go with the dumb version for now. Maybe I should use a 573 benaphore? 574 575 BeBook mentions handling the case where the handler's looper 576 changes during this call. I've attempted a "pseudo-atomic" 577 operation to check for that. 578 */ 579 BLooper* Looper = fLooper; 580 if (Looper) 581 { 582 status_t result = Looper->LockWithTimeout(timeout); 583 584 // Are we still assigned to the same looper? 585 if (fLooper == Looper) 586 { 587 return result; 588 } 589 else 590 { 591 // Our looper changed during the lock attempt 592 if (result == B_OK) 593 { 594 // The lock was successful on the old looper; undo the lock 595 Looper->Unlock(); 596 } 597 598 return B_MISMATCHED_VALUES; 599 } 600 } 601 602 return B_BAD_VALUE; 603 } 604 //------------------------------------------------------------------------------ 605 void BHandler::UnlockLooper() 606 { 607 /** 608 @note BeBook says that this function "retrieves the handler's looper and 609 unlocks it in a pseudo-atomic operation, thus avoiding a race 610 condition." How "pseudo-atomic" would look completely escapes me, 611 so we'll go with the dumb version for now. Maybe I should use a 612 benaphore? 613 614 The solution I used for Lock() and LockWithTimeout() seems out of 615 place here; if our looper does change while attempting to unlock it, 616 re-Lock()ing the original looper just doesn't seem right. 617 */ 618 // TODO: implement correctly 619 BLooper* Looper = fLooper; 620 if (Looper) 621 { 622 Looper->Unlock(); 623 } 624 } 625 //------------------------------------------------------------------------------ 626 BHandler* BHandler::ResolveSpecifier(BMessage* msg, int32 index, 627 BMessage* specifier, int32 form, 628 const char* property) 629 { 630 // Straight from the BeBook 631 BPropertyInfo PropertyInfo(gHandlerPropInfo); 632 if (PropertyInfo.FindMatch(msg, index, specifier, form, property) >= 0) 633 { 634 return this; 635 } 636 637 BMessage Reply(B_MESSAGE_NOT_UNDERSTOOD); 638 Reply.AddInt32("error", B_BAD_SCRIPT_SYNTAX); 639 Reply.AddString("message", "Didn't understand the specifier(s)"); 640 msg->SendReply(&Reply); 641 642 return NULL; 643 } 644 //------------------------------------------------------------------------------ 645 status_t BHandler::GetSupportedSuites(BMessage* data) 646 { 647 /** 648 @note This is the output from the original implementation (calling 649 PrintToStream() on both data and the contained BPropertyInfo): 650 651 BMessage: what = (0x0, or 0) 652 entry suites, type='CSTR', c=1, size=21, data[0]: "suite/vnd.Be-handler" 653 entry messages, type='SCTD', c=1, size= 0, 654 property commands types specifiers 655 -------------------------------------------------------------------------------- 656 Suites PGET 1 657 (RTSC,suites) 658 (DTCS,messages) 659 660 Messenger PGET GNSM 1 661 InternalName PGET RTSC 1 662 663 With a good deal of trial and error, I determined that the 664 parenthetical clauses are entries in the 'ctypes' field of 665 property_info. 'ctypes' is an array of 'compound_type', which 666 contains an array of 'field_pair's. I haven't the foggiest what 667 either 'compound_type' or 'field_pair' is for, being as the 668 scripting docs are so bloody horrible. The corresponding 669 property_info array is declared in the globals section. 670 */ 671 status_t err = B_OK; 672 if (!data) 673 { 674 err = B_BAD_VALUE; 675 } 676 677 if (!err) 678 { 679 err = data->AddString("suites", "suite/vnd.Be-handler"); 680 if (!err) 681 { 682 BPropertyInfo PropertyInfo(gHandlerPropInfo); 683 err = data->AddFlat("message", &PropertyInfo); 684 } 685 } 686 687 return err; 688 } 689 //------------------------------------------------------------------------------ 690 status_t BHandler::StartWatching(BMessenger Messenger, uint32 what) 691 { 692 fObserverList ? fObserverList : fObserverList = new _ObserverList; 693 return fObserverList->StartObserving(Messenger, what); 694 } 695 //------------------------------------------------------------------------------ 696 status_t BHandler::StartWatchingAll(BMessenger Messenger) 697 { 698 fObserverList ? fObserverList : fObserverList = new _ObserverList; 699 return fObserverList->StartObserving(Messenger, B_OBSERVER_OBSERVE_ALL); 700 } 701 //------------------------------------------------------------------------------ 702 status_t BHandler::StopWatching(BMessenger Messenger, uint32 what) 703 { 704 fObserverList ? fObserverList : fObserverList = new _ObserverList; 705 return fObserverList->StopObserving(Messenger, what); 706 } 707 //------------------------------------------------------------------------------ 708 status_t BHandler::StopWatchingAll(BMessenger Messenger) 709 { 710 fObserverList ? fObserverList : fObserverList = new _ObserverList; 711 return fObserverList->StopObserving(Messenger, B_OBSERVER_OBSERVE_ALL); 712 } 713 //------------------------------------------------------------------------------ 714 status_t BHandler::StartWatching(BHandler* Handler, uint32 what) 715 { 716 fObserverList ? fObserverList : fObserverList = new _ObserverList; 717 return fObserverList->StartObserving(Handler, what); 718 } 719 //------------------------------------------------------------------------------ 720 status_t BHandler::StartWatchingAll(BHandler* Handler) 721 { 722 fObserverList ? fObserverList : fObserverList = new _ObserverList; 723 return fObserverList->StartObserving(Handler, B_OBSERVER_OBSERVE_ALL); 724 } 725 //------------------------------------------------------------------------------ 726 status_t BHandler::StopWatching(BHandler* Handler, uint32 what) 727 { 728 fObserverList ? fObserverList : fObserverList = new _ObserverList; 729 return fObserverList->StopObserving(Handler, what); 730 } 731 //------------------------------------------------------------------------------ 732 status_t BHandler::StopWatchingAll(BHandler* Handler) 733 { 734 fObserverList ? fObserverList : fObserverList = new _ObserverList; 735 return fObserverList->StopObserving(Handler, B_OBSERVER_OBSERVE_ALL); 736 } 737 //------------------------------------------------------------------------------ 738 status_t BHandler::Perform(perform_code d, void* arg) 739 { 740 return BArchivable::Perform(d, arg); 741 } 742 //------------------------------------------------------------------------------ 743 void BHandler::SendNotices(uint32 what, const BMessage* msg) 744 { 745 fObserverList ? fObserverList : fObserverList = new _ObserverList; 746 fObserverList->SendNotices(what, msg); 747 } 748 //------------------------------------------------------------------------------ 749 bool BHandler::IsWatched() const 750 { 751 return fObserverList && !fObserverList->IsEmpty(); 752 } 753 //------------------------------------------------------------------------------ 754 void BHandler::_ReservedHandler2() 755 { 756 // Unused 757 ; 758 } 759 //------------------------------------------------------------------------------ 760 void BHandler::_ReservedHandler3() 761 { 762 // Unused 763 ; 764 } 765 //------------------------------------------------------------------------------ 766 void BHandler::_ReservedHandler4() 767 { 768 // Unused 769 ; 770 } 771 //------------------------------------------------------------------------------ 772 void BHandler::InitData(const char* name) 773 { 774 SetName(name); 775 776 fLooper = NULL; 777 fNextHandler = NULL; 778 fFilters = NULL; 779 fObserverList = NULL; 780 781 fToken = gDefaultTokens.NewToken(B_HANDLER_TOKEN, this); 782 } 783 //------------------------------------------------------------------------------ 784 BHandler::BHandler(const BHandler& ) 785 { 786 // No copy construction allowed. 787 ; 788 } 789 //------------------------------------------------------------------------------ 790 BHandler& BHandler::operator=(const BHandler& ) 791 { 792 // No assignments allowed. 793 return *this; 794 } 795 //------------------------------------------------------------------------------ 796 void BHandler::SetLooper(BLooper* loop) 797 { 798 fLooper = loop; 799 } 800 //------------------------------------------------------------------------------ 801 802 803 //------------------------------------------------------------------------------ 804 // #pragma mark - 805 // #pragma mark _ObserverList 806 // #pramga mark - 807 //------------------------------------------------------------------------------ 808 _ObserverList::_ObserverList(void) 809 { 810 } 811 //------------------------------------------------------------------------------ 812 _ObserverList::~_ObserverList(void) 813 { 814 } 815 //------------------------------------------------------------------------------ 816 status_t _ObserverList::SendNotices(unsigned long what, BMessage const* Message) 817 { 818 // Having to new a temporary is really irritating ... 819 BMessage* CopyMsg = NULL; 820 if (Message) 821 { 822 CopyMsg = new BMessage(*Message); 823 CopyMsg->what = B_OBSERVER_NOTICE_CHANGE; 824 CopyMsg->AddInt32(B_OBSERVE_ORIGINAL_WHAT, Message->what); 825 } 826 else 827 { 828 CopyMsg = new BMessage(B_OBSERVER_NOTICE_CHANGE); 829 } 830 831 CopyMsg->AddInt32(B_OBSERVE_WHAT_CHANGE, what); 832 833 vector<BHandler*>& Handlers = fHandlerMap[what]; 834 for (uint32 i = 0; i < Handlers.size(); ++i) 835 { 836 BMessenger msgr(Handlers[i]); 837 msgr.SendMessage(CopyMsg); 838 } 839 840 vector<BMessenger>& Messengers = fMessengerMap[what]; 841 for (uint32 i = 0; i < Messengers.size(); ++i) 842 { 843 Messengers[i].SendMessage(CopyMsg); 844 } 845 846 // Gotta make sure to clean up the annoying temporary ... 847 delete CopyMsg; 848 849 return B_OK; 850 } 851 //------------------------------------------------------------------------------ 852 status_t _ObserverList::StartObserving(BHandler* Handler, unsigned long what) 853 { 854 if (!Handler) 855 { 856 return B_BAD_HANDLER; 857 } 858 859 vector<BHandler*>& Handlers = fHandlerMap[what]; 860 vector<BHandler*>::iterator iter; 861 iter = find(Handlers.begin(), Handlers.end(), Handler); 862 if (iter != Handlers.end()) 863 { 864 // TODO: verify 865 return B_OK; 866 } 867 868 Handlers.push_back(Handler); 869 return B_OK; 870 } 871 //------------------------------------------------------------------------------ 872 status_t _ObserverList::StartObserving(const BMessenger& Messenger, 873 unsigned long what) 874 { 875 vector<BMessenger>& Messengers = fMessengerMap[what]; 876 vector<BMessenger>::iterator iter; 877 iter = find(Messengers.begin(), Messengers.end(), Messenger); 878 if (iter != Messengers.end()) 879 { 880 // TODO: verify 881 return B_OK; 882 } 883 884 Messengers.push_back(Messenger); 885 return B_OK; 886 } 887 //------------------------------------------------------------------------------ 888 status_t _ObserverList::StopObserving(BHandler* Handler, unsigned long what) 889 { 890 if (Handler) 891 { 892 vector<BHandler*>& Handlers = fHandlerMap[what]; 893 vector<BHandler*>::iterator iter; 894 iter = find(Handlers.begin(), Handlers.end(), Handler); 895 if (iter != Handlers.end()) 896 { 897 Handlers.erase(iter); 898 if (Handlers.empty()) 899 { 900 fHandlerMap.erase(what); 901 } 902 return B_OK; 903 } 904 } 905 906 return B_BAD_HANDLER; 907 } 908 //------------------------------------------------------------------------------ 909 status_t _ObserverList::StopObserving(const BMessenger& Messenger, 910 unsigned long what) 911 { 912 // ???: What if you call StartWatching(MyMsngr, aWhat) and then call 913 // StopWatchingAll(MyMsnger)? Will MyMsnger be removed from the aWhat 914 // watcher list? For now, we'll assume that they're discreet lists 915 // which do no cross checking; i.e., MyMsnger would *not* be removed in 916 // this scenario. 917 vector<BMessenger>& Messengers = fMessengerMap[what]; 918 vector<BMessenger>::iterator iter; 919 iter = find(Messengers.begin(), Messengers.end(), Messenger); 920 if (iter != Messengers.end()) 921 { 922 Messengers.erase(iter); 923 if (Messengers.empty()) 924 { 925 fMessengerMap.erase(what); 926 } 927 return B_OK; 928 } 929 930 return B_BAD_HANDLER; 931 } 932 //------------------------------------------------------------------------------ 933 bool _ObserverList::IsEmpty() 934 { 935 return fHandlerMap.empty() && fMessengerMap.empty(); 936 } 937 //------------------------------------------------------------------------------ 938 939 940 //------------------------------------------------------------------------------ 941 bool FilterDeleter(void* filter) 942 { 943 BMessageFilter* Filter = static_cast<BMessageFilter*>(filter); 944 if (Filter) 945 { 946 delete Filter; 947 Filter = NULL; 948 } 949 950 return false; 951 } 952 //------------------------------------------------------------------------------ 953 954 /* 955 * $Log $ 956 * 957 * $Id $ 958 * 959 */ 960 961