Ticket #6256: archivable.patch
File archivable.patch, 23.2 KB (added by , 14 years ago) |
---|
-
src/kits/support/Archivable.cpp
1 1 /* 2 * Copyright (c) 2001-20 08, Haiku, Inc.2 * Copyright (c) 2001-2010, Haiku, Inc. 3 3 * Distributed under the terms of the MIT License. 4 4 * 5 5 * Authors: 6 6 * Erik Jaesler (erik@cgsoftware.com) 7 * Alex Wilson (yourpalal2@gmail.com) 7 8 */ 8 9 9 10 /*! BArchivable mix-in class defines the archiving protocol. … … 13 14 14 15 #include <ctype.h> 15 16 #include <errno.h> 17 #include <new> 18 #include <set> 16 19 #include <stdlib.h> 17 20 #include <stdio.h> 18 21 #include <string> … … 22 25 23 26 #include <AppFileInfo.h> 24 27 #include <Archivable.h> 28 #include <ArchivablePrivate.h> 25 29 #include <Entry.h> 26 30 #include <List.h> 27 31 #include <OS.h> … … 33 37 using std::string; 34 38 using std::vector; 35 39 40 using namespace BPrivate::Archiving; 41 36 42 const char* B_CLASS_FIELD = "class"; 37 43 const char* B_ADD_ON_FIELD = "add_on"; 38 44 const int32 FUNC_NAME_LEN = 1024; 39 45 46 const char* kArchiveCountField = "_managed_archive_count"; 47 40 48 // TODO: consider moving these to a separate module, and making them more 41 49 // full-featured (e.g., taking NS::ClassName::Function(Param p) instead 42 50 // of just NS::ClassName) … … 209 217 210 218 BArchivable::BArchivable(BMessage* from) 211 219 { 220 if (BUnarchiver::ArchiveIsManaged(from)) { 221 BUnarchiver::PrepareArchive(from); 222 BUnarchiver(from).RegisterArchivable(this); 223 } 212 224 } 213 225 214 226 … … 225 237 return B_BAD_VALUE; 226 238 } 227 239 240 BArchiver::PrepareArchive(into); 241 BArchiver(into).RegisterArchivable(this); 242 228 243 BString name; 229 244 status_t status = demangle_class_name(typeid(*this).name(), name); 230 245 if (status != B_OK) … … 250 265 } 251 266 252 267 253 void BArchivable::_ReservedArchivable1() {} 254 void BArchivable::_ReservedArchivable2() {} 255 void BArchivable::_ReservedArchivable3() {} 268 status_t 269 BArchivable::AllUnarchived(const BMessage* archive) 270 { 271 return B_OK; 272 } 256 273 274 // #pragma mark - 257 275 276 BArchiver::BArchiver(BMessage* archive) 277 : 278 fManager(_RetrieveManager(archive)), 279 fArchive(archive) 280 { 281 if (!fManager) 282 debugger("BArchiver constructed with unprepared BMessage"); 283 } 284 285 286 BArchiver::~BArchiver() 287 { 288 fManager->ArchiverLeaving(this); 289 } 290 291 292 status_t 293 BArchiver::AddArchivable(const char* name, BArchivable* archivable, bool deep) 294 { 295 int32 token; 296 status_t err = fManager->TokenForArchivable(archivable, deep, token); 297 if (err != B_OK) 298 return err; 299 300 return fArchive->AddInt32(name, token); 301 } 302 303 304 bool 305 BArchiver::AddOptional(const char* name, BArchivable* archivable) 306 { 307 int32 token; 308 status_t err = fManager->TokenForOptional(archivable, token); 309 if (err != B_OK) 310 return false; 311 312 err = fArchive->AddInt32(name, token); 313 314 return (err == B_OK); 315 } 316 317 318 status_t 319 BArchiver::AddPendingArchival(const char* name, BArchivable* archivable) 320 { 321 if (AddOptional(name, archivable)) 322 return B_OK; 323 324 return fManager->AddTokenPendingArchival(fArchive, name, archivable); 325 } 326 327 328 BMessage* 329 BArchiver::PrepareArchive(BMessage* archive) 330 { 331 BArchiveManager* manager = _RetrieveManager(archive); 332 if (!manager) 333 manager = new BArchiveManager(archive); 334 manager->Acquire(); 335 return archive; 336 } 337 338 339 void 340 BArchiver::RegisterArchivable(const BArchivable* archivable) 341 { 342 fManager->RegisterArchivable(archivable); 343 } 344 345 346 BArchiveManager* 347 BArchiver::_RetrieveManager(BMessage* archive) 348 { 349 return BManagerBase::ArchiveManager(archive); 350 } 351 352 258 353 // #pragma mark - 259 354 260 355 356 BUnarchiver::BUnarchiver(const BMessage* archive) 357 : 358 fManager(_RetrieveManager(const_cast<BMessage*>(archive))), 359 fArchive(archive) 360 { 361 if (!fManager) { 362 syslog(LOG_ERR, "BUnarchiver constructed with" 363 " unprepared or unmanaged BMessage"); 364 } 365 } 366 367 368 BUnarchiver::~BUnarchiver() 369 { 370 if (fManager) 371 fManager->UnarchiverLeaving(this); 372 } 373 374 375 status_t 376 BUnarchiver::FindArchivable(const char* name, BArchivable** archivable) 377 { 378 return FindArchivable(name, 0, archivable); 379 } 380 381 382 status_t 383 BUnarchiver::FindArchivable(const char* name, 384 int32 index, BArchivable** archivable) 385 { 386 _CallDebuggerIfManagerNull(); 387 388 if (archivable == NULL) 389 return B_BAD_VALUE; 390 391 int32 token; 392 status_t err = fArchive->FindInt32(name, index, &token); 393 if (err != B_OK) 394 return err; 395 396 return fManager->ArchivableForToken(archivable, token); 397 } 398 399 400 status_t 401 BUnarchiver::EnsureUnarchived(const char* name, int32 index) 402 { 403 BArchivable* retriever; 404 return FindArchivable(name, index, &retriever); 405 } 406 407 408 const BMessage* 409 BUnarchiver::ArchiveMessage() const 410 { 411 return fArchive; 412 } 413 414 415 bool 416 BUnarchiver::ArchiveIsManaged(BMessage* archive) 417 { 418 // managed child archives will return here 419 if (BManagerBase::ManagerPointer(archive)) 420 return true; 421 422 // managed top level archives return here 423 int32 dummy; 424 if (archive->FindInt32(kArchiveCountField, &dummy) == B_OK) 425 return true; 426 427 return false; 428 } 429 430 431 BMessage* 432 BUnarchiver::PrepareArchive(BMessage* archive) 433 { 434 // this check allows PrepareArchive to be 435 // called on new or old-style archives 436 if (BUnarchiver::ArchiveIsManaged(archive)) { 437 BUnarchiveManager* manager = _RetrieveManager(archive); 438 if (!manager) 439 manager = new BUnarchiveManager(archive); 440 manager->Acquire(); 441 } 442 return archive; 443 } 444 445 446 void 447 BUnarchiver::RegisterArchivable(BArchivable* archivable) 448 { 449 _CallDebuggerIfManagerNull(); 450 fManager->RegisterArchivable(archivable); 451 } 452 453 454 BUnarchiveManager* 455 BUnarchiver::_RetrieveManager(BMessage* archive) 456 { 457 return BManagerBase::UnarchiveManager(archive); 458 } 459 460 461 void 462 BUnarchiver::_CallDebuggerIfManagerNull() 463 { 464 if (!fManager) 465 debugger("BUnarchiver used with legacy or unprepared archive."); 466 } 467 468 469 // #pragma mark - 470 471 472 namespace { 473 BString 474 ArchiveFieldNameForToken(int32 token) 475 { 476 return BString("managed_archivable_") << token; 477 } 478 } 479 480 481 // #pragma mark - 482 483 484 BArchiveManager* 485 BManagerBase::ArchiveManager(BMessage* archive) 486 { 487 BManagerBase* manager = ManagerPointer(archive); 488 if (!manager) 489 return NULL; 490 491 if (manager->fType == ARCHIVE_MANAGER) 492 return static_cast<BArchiveManager*>(manager); 493 494 debugger("More calls to BArchiver::PrepareMessage() than BArchivers created"); 495 return NULL; 496 } 497 498 499 BUnarchiveManager* 500 BManagerBase::UnarchiveManager(BMessage* archive) 501 { 502 BManagerBase* manager = ManagerPointer(archive); 503 if (!manager) 504 return NULL; 505 506 if (manager->fType == UNARCHIVE_MANAGER) 507 return static_cast<BUnarchiveManager*>(manager); 508 509 debugger("More calls to BUnarchiver::PrepareMessage()" 510 " than BUnarchivers created"); 511 512 return NULL; 513 } 514 515 516 // #pragma mark - 517 518 519 BArchiveManager::BArchiveManager(BMessage* topLevelArchive) 520 : 521 BManagerBase(topLevelArchive, BManagerBase::ARCHIVE_MANAGER), 522 fTokenMap(), 523 fPendingActions(20, true), 524 fRefcount(0) 525 { 526 } 527 528 529 BArchiveManager::~BArchiveManager() 530 { 531 _CompletePendingActions(); 532 fTopLevelArchive->AddInt32(kArchiveCountField, fTokenMap.size()); 533 } 534 535 536 status_t 537 BArchiveManager::TokenForArchivable(BArchivable* archivable, 538 bool deep, int32& _token) 539 { 540 if (TokenForOptional(archivable, _token) == B_OK) 541 return B_OK; 542 543 _token = fTokenMap.size(); 544 fTokenMap[archivable] = _token; 545 546 status_t err = _ArchiveObject(archivable, _token, deep); 547 if (err != B_OK) 548 fTokenMap.erase(archivable); 549 return err; 550 } 551 552 553 status_t 554 BArchiveManager::TokenForOptional(BArchivable* archivable, int32& _token) 555 { 556 if (!archivable) { 557 _token = -42; 558 return B_OK; 559 } 560 561 std::map<const BArchivable*, int32>::iterator it = fTokenMap.find(archivable); 562 if (it == fTokenMap.end()) 563 return B_ERROR; 564 565 _token = it->second; 566 return B_OK; 567 } 568 569 570 status_t 571 BArchiveManager::AddTokenPendingArchival(BMessage* into, const char* name, 572 BArchivable* archivable) 573 { 574 PendingAction* action = new(std::nothrow) PendingAction(); 575 if (action && fPendingActions.AddItem(action)) { 576 action->intoArchive = into; 577 action->archiveField = name; 578 action->requested = archivable; 579 return B_OK; 580 } 581 582 return B_NO_MEMORY; 583 } 584 585 586 void 587 BArchiveManager::ArchiverLeaving(const BArchiver* archiver) 588 { 589 if (--fRefcount == 0) 590 delete this; 591 } 592 593 594 void 595 BArchiveManager::Acquire() 596 { 597 fRefcount++; 598 } 599 600 601 void 602 BArchiveManager::RegisterArchivable(const BArchivable* archivable) 603 { 604 if (fTokenMap.size() == 0) 605 fTokenMap[archivable] = 0; 606 } 607 608 609 status_t 610 BArchiveManager::_ArchiveObject(BArchivable* object, int32 token, bool deep) 611 { 612 BMessage childArchive; 613 MarkArchive(&childArchive); 614 615 int32 pendingActionsCount = fPendingActions.CountItems(); 616 status_t err = object->Archive(&childArchive, deep); 617 618 if (err == B_OK && !_ProcessNewPendingActions( 619 pendingActionsCount, &childArchive, token, err)) { 620 return fTopLevelArchive->AddMessage( 621 ArchiveFieldNameForToken(token), &childArchive); 622 } 623 624 return err; 625 } 626 627 628 /*! 629 \retval true there are valid pending actions for this archive 630 \retval false there are no valid pending actions 631 */ 632 bool 633 BArchiveManager::_ProcessNewPendingActions(int32 start, BMessage* forArchive, 634 int32 token, status_t error) 635 { 636 BMessage* archive = NULL; 637 for (int32 index = fPendingActions.CountItems() -1; index >= start; index --) { 638 PendingAction* action = fPendingActions.ItemAt(index); 639 BMessage*& currentArchive = action->intoArchive; 640 641 if (currentArchive == forArchive) { 642 if (error != B_OK) { 643 fPendingActions.RemoveItemAt(index); 644 continue; 645 } 646 if (archive == NULL) 647 archive = new BMessage(*forArchive); 648 currentArchive = archive; 649 action->archiveToken = token; 650 } 651 } 652 return (error == B_OK && archive != NULL); 653 } 654 655 656 void 657 BArchiveManager::_CompletePendingActions() 658 { 659 if (fPendingActions.CountItems() == 0) 660 return; 661 662 663 for (int32 i = fPendingActions.CountItems() - 1; i >= 0; i--) { 664 PendingAction* action = fPendingActions.ItemAt(i); 665 666 int32 token; 667 if (TokenForOptional(action->requested, token) == B_OK) 668 action->intoArchive->AddInt32(action->archiveField, token); 669 } 670 671 std::set<BMessage*> finishedMessages; 672 finishedMessages.insert(fTopLevelArchive); 673 674 for (int32 i = fPendingActions.CountItems() - 1; i >= 0; i--) { 675 676 PendingAction* action = fPendingActions.ItemAt(i); 677 BMessage* archive = action->intoArchive; 678 int32 token = action->archiveToken; 679 680 if ((finishedMessages.insert(archive)).second == true) { 681 fTopLevelArchive->AddMessage(ArchiveFieldNameForToken(token), 682 archive); 683 delete archive; 684 } 685 } 686 } 687 688 689 // #pragma mark - 690 691 692 BUnarchiveManager::BUnarchiveManager(BMessage* archive) 693 : 694 BManagerBase(archive, BManagerBase::UNARCHIVE_MANAGER), 695 fObjects(NULL), 696 fObjectCount(0), 697 fTokensInProgress(), 698 fRefcount(0) 699 { 700 archive->FindInt32(kArchiveCountField, &fObjectCount); 701 fObjects = new ArchiveInfo[fObjectCount]; 702 703 fTokensInProgress.push(0); 704 // fObjects[0] is a placeholder representing the 705 // BArchivable that has created us, and fTopLevelArchive 706 for (int32 i = 1; i < fObjectCount; i++) 707 _ArchiveForToken(&fObjects[i].archive, i); 708 } 709 710 711 BUnarchiveManager::~BUnarchiveManager() 712 { 713 _EnterDestructor(); 714 715 if (fObjects[0].archivable->AllUnarchived(fTopLevelArchive) != B_OK) 716 syslog(LOG_ERR, "AllUnarchived failed for root object."); 717 718 for (int32 i = 1; i < fObjectCount; i++) { 719 BArchivable*& archivable = fObjects[i].archivable; 720 if (archivable && 721 (archivable->AllUnarchived(&fObjects[i].archive) != B_OK)) { 722 723 syslog(LOG_ERR, "AllUnarchived failed, BArchivable" 724 " object will be deleted"); 725 delete archivable; 726 archivable = NULL; 727 } 728 } 729 delete[] fObjects; 730 } 731 732 733 status_t 734 BUnarchiveManager::ArchivableForToken(BArchivable** _archivable, int32 token) 735 { 736 if (!_archivable || token > fObjectCount) 737 return B_BAD_VALUE; 738 739 if (token < 0) { 740 *_archivable = NULL; 741 return B_OK; 742 } 743 744 status_t err = B_OK; 745 if (!fObjects[token].archivable) { 746 if (!_InDestructor()) 747 err = _InstantiateObjectForToken(token); 748 else { 749 syslog(LOG_ERR, "Object requested from AllUnarchived()" 750 " was not previously instantiated"); 751 err = B_ERROR; 752 } 753 } 754 755 *_archivable = fObjects[token].archivable; 756 return err; 757 } 758 759 760 void 761 BUnarchiveManager::RegisterArchivable(BArchivable* archivable) 762 { 763 fObjects[fTokensInProgress.top()].archivable = archivable; 764 fTokensInProgress.pop(); 765 } 766 767 768 void 769 BUnarchiveManager::UnarchiverLeaving(const BUnarchiver* unarchiver) 770 { 771 if (--fRefcount == 0) 772 delete this; 773 } 774 775 776 void 777 BUnarchiveManager::Acquire() 778 { 779 if (!_InDestructor()) 780 fRefcount++; 781 } 782 783 784 status_t 785 BUnarchiveManager::_ArchiveForToken(BMessage* archive, int32 token) 786 { 787 status_t err = fTopLevelArchive->FindMessage( 788 ArchiveFieldNameForToken(token), archive); 789 790 if (err == B_OK) 791 MarkArchive(archive); 792 793 return err; 794 } 795 796 797 status_t 798 BUnarchiveManager::_InstantiateObjectForToken(int32 token) 799 { 800 fTokensInProgress.push(token); 801 if (!instantiate_object(&fObjects[token].archive)) { 802 fTokensInProgress.pop(); 803 return B_ERROR; 804 } 805 return B_OK; 806 } 807 808 809 bool 810 BUnarchiveManager::_InDestructor() 811 { 812 return (fRefcount < 0); 813 } 814 815 816 void 817 BUnarchiveManager::_EnterDestructor() 818 { 819 fRefcount = -1; 820 } 821 822 823 // #pragma mark - 824 825 261 826 BArchivable* 262 827 instantiate_object(BMessage* archive, image_id* _id) 263 828 { … … 475 1040 return find_instantiation_func(name, signature); 476 1041 } 477 1042 1043 // BArchivable binary compatability 1044 #if __GNUC__ == 2 1045 1046 // TODO: make sure this is the correct signature 1047 extern "C" status_t 1048 _ReservedArchivable1__11BArchivable(BArchivable* archivable, 1049 const BMessage* archive) 1050 { 1051 return archivable->AllUnarchived(archive); 1052 } 1053 1054 #elif __GNUC__ > 2 1055 1056 extern "C" status_t 1057 _ZN11BArchivable20_ReservedArchivable1Ev(BArchivable* archivable, 1058 const BMessage* archive) 1059 { 1060 return archivable->AllUnarchived(archive); 1061 } 1062 1063 #endif // _GNUC__ > 2 1064 1065 void BArchivable::_ReservedArchivable2() {} 1066 void BArchivable::_ReservedArchivable3() {} 1067 1068 -
headers/os/support/Archivable.h
1 1 /* 2 * Copyright 2001-20 07, Haiku, Inc. All Rights Reserved.2 * Copyright 2001-2010, Haiku, Inc. All Rights Reserved. 3 3 * Distributed under the terms of the MIT License. 4 4 */ 5 5 #ifndef _ARCHIVABLE_H … … 12 12 13 13 class BMessage; 14 14 15 namespace BPrivate { 16 namespace Archiving { 17 class BArchiveManager; 18 class BUnarchiveManager; 19 } 20 } 15 21 22 using BPrivate::Archiving::BArchiveManager; 23 using BPrivate::Archiving::BUnarchiveManager; 24 25 16 26 class BArchivable { 17 18 19 20 27 public: 28 BArchivable(BMessage* from); 29 BArchivable(); 30 virtual ~BArchivable(); 21 31 22 23 32 virtual status_t Archive(BMessage* into, bool deep = true) const; 33 static BArchivable* Instantiate(BMessage* archive); 24 34 25 // Private or reserved 26 virtual status_t Perform(perform_code d, void* arg); 35 virtual status_t Perform(perform_code d, void* arg); 27 36 28 private: 29 virtual void _ReservedArchivable1(); 30 virtual void _ReservedArchivable2(); 31 virtual void _ReservedArchivable3(); 37 // In the context of an unarchiving session (using BUnarchiver) 38 // returning a value other than B_OK here means this object is 39 // not valid, so it will be deleted, and any further attempts 40 // to retrieve if (via BUnarchiver::FindArchivable()) will give 41 // a NULL pointer. If there was an error, but this object is 42 // still valid, return B_OK. 43 virtual status_t AllUnarchived(const BMessage* archive); 32 44 33 uint32 _reserved[2]; 45 private: 46 virtual void _ReservedArchivable2(); 47 virtual void _ReservedArchivable3(); 48 49 uint32 _reserved[2]; 34 50 }; 35 51 36 52 53 class BArchiver { 54 public: 55 BArchiver(BMessage* archive); 56 BArchiver(); // not defined 57 ~BArchiver(); 58 59 status_t AddArchivable(const char* name, 60 BArchivable* archivable, bool deep = true); 61 62 // AddOptional will only add the object if it has 63 // already been archived. Whether or not the object is added 64 // should not be crucial to successful archiving 65 // (it should be optional). 66 bool AddOptional(const char* name, 67 BArchivable* archivable); 68 69 status_t AddPendingArchival(const char* name, 70 BArchivable* archivable); 71 // archivable will be added if it is archived in this session 72 73 const BMessage* ArchiveMessage() const; 74 75 static BMessage* PrepareArchive(BMessage* archive); 76 private: 77 friend class BArchivable; 78 79 void RegisterArchivable(const BArchivable* archivable); 80 81 static BArchiveManager* _RetrieveManager(BMessage* archive); 82 83 BArchiveManager* fManager; 84 BMessage* fArchive; 85 }; 86 87 88 class BUnarchiver { 89 public: 90 BUnarchiver(const BMessage* archive); 91 BUnarchiver(); // not defined 92 ~BUnarchiver(); 93 94 status_t FindArchivable(const char* name, 95 BArchivable** archivable); 96 97 status_t FindArchivable(const char* name, int32 index, 98 BArchivable** archivable); 99 100 status_t EnsureUnarchived(const char* name, int32 index = 0); 101 102 const BMessage* ArchiveMessage() const; 103 104 static bool ArchiveIsManaged(BMessage* archive); 105 static BMessage* PrepareArchive(BMessage* archive); 106 private: 107 friend class BArchivable; 108 109 void RegisterArchivable(BArchivable* archivable); 110 111 static BUnarchiveManager* _RetrieveManager(BMessage* archive); 112 void _CallDebuggerIfManagerNull(); 113 114 BUnarchiveManager* fManager; 115 const BMessage* fArchive; 116 }; 117 118 37 119 // global functions 38 120 39 121 typedef BArchivable* (*instantiation_func)(BMessage*); 40 122 41 BArchivable* instantiate_object(BMessage *from, image_id *id);42 BArchivable* instantiate_object(BMessage *from);123 BArchivable* instantiate_object(BMessage* from, image_id* id); 124 BArchivable* instantiate_object(BMessage* from); 43 125 bool validate_instantiation(BMessage* from, const char* className); 44 126 45 127 instantiation_func find_instantiation_func(const char* className, -
headers/private/support/ArchivablePrivate.h
1 #ifndef _ARCHIVABLE_PRIVATE_H 2 #define _ARCHIVABLE_PRIVATE_H 3 /* 4 * Copyright 2010, Haiku, Inc. All Rights Reserved. 5 * Distributed under the terms of the MIT License. 6 */ 7 8 #include <map> 9 #include <stack> 10 11 #include <String.h> 12 #include <ObjectList.h> 13 #include <MessagePrivate.h> 14 15 #include <Archivable.h> 16 17 18 namespace BPrivate { 19 namespace Archiving { 20 21 22 class BManagerBase { 23 public: 24 enum manager_type { 25 ARCHIVE_MANAGER, 26 UNARCHIVE_MANAGER 27 }; 28 29 BManagerBase(BMessage* topLevelArchive, manager_type type) 30 : 31 fTopLevelArchive(topLevelArchive), 32 fType(type) 33 { 34 MarkArchive(topLevelArchive); 35 } 36 37 38 ~BManagerBase() 39 { 40 UnmarkArchive(fTopLevelArchive); 41 } 42 43 44 static BManagerBase* 45 ManagerPointer(BMessage* archive) 46 { 47 return static_cast<BManagerBase*>( 48 BMessage::Private(archive).ArchivingPointer()); 49 } 50 51 52 static void 53 SetManagerPointer(BMessage* archive, BManagerBase* manager) 54 { 55 BMessage::Private(archive).ArchivingPointer() = static_cast<void*>(manager); 56 } 57 58 59 void 60 MarkArchive(BMessage* archive) 61 { 62 BManagerBase* manager = ManagerPointer(archive); 63 if (manager != NULL && manager != this) 64 debugger("Overlapping managed archiving/unarchiving sessions!"); 65 66 SetManagerPointer(archive, this); 67 } 68 69 70 void 71 UnmarkArchive(BMessage* archive) 72 { 73 BManagerBase* manager = ManagerPointer(archive); 74 if (manager == this) 75 SetManagerPointer(archive, NULL); 76 else 77 debugger("Overlapping managed archiving/unarchiving sessions!"); 78 } 79 80 81 static BArchiveManager* ArchiveManager(BMessage* archive); 82 static BUnarchiveManager* UnarchiveManager(BMessage* archive); 83 84 protected: 85 BMessage* fTopLevelArchive; 86 manager_type fType; 87 }; 88 89 90 struct PendingAction { 91 PendingAction() 92 : 93 requested(NULL), 94 intoArchive(NULL), 95 archiveField(NULL), 96 archiveToken(0) 97 { 98 } 99 100 BArchivable* requested; 101 BMessage* intoArchive; 102 BString archiveField; 103 int32 archiveToken; 104 }; 105 106 107 class BArchiveManager: public BManagerBase { 108 public: 109 BArchiveManager(BMessage* topLevelArchive); 110 ~BArchiveManager(); 111 112 status_t TokenForArchivable(BArchivable* archivable, 113 bool deep, int32& _token); 114 115 status_t TokenForOptional(BArchivable* archivable, 116 int32& _token); 117 118 status_t AddTokenPendingArchival(BMessage* into, 119 const char* archiveField, BArchivable* archivable); 120 121 void ArchiverLeaving(const BArchiver* archiver); 122 void Acquire(); 123 void RegisterArchivable(const BArchivable* archivable); 124 125 private: 126 status_t _ArchiveObject(BArchivable* object, 127 int32 token, bool deep); 128 bool _ProcessNewPendingActions(int32 startIndex, 129 BMessage* forArchive, int32 token, status_t error); 130 void _CompletePendingActions(); 131 132 std::map<const BArchivable*, int32> fTokenMap; 133 BObjectList<PendingAction> fPendingActions; 134 int32 fRefcount; 135 }; 136 137 138 struct ArchiveInfo { 139 ArchiveInfo() 140 : 141 archivable(NULL), 142 archive() 143 { 144 } 145 146 bool 147 operator<(const ArchiveInfo& other) 148 { 149 return archivable < other.archivable; 150 } 151 152 BArchivable* archivable; 153 BMessage archive; 154 }; 155 156 157 class BUnarchiveManager: public BManagerBase { 158 public: 159 BUnarchiveManager(BMessage* topLevelArchive); 160 ~BUnarchiveManager(); 161 162 status_t ArchivableForToken(BArchivable** archivable, int32 token); 163 void RegisterArchivable(BArchivable* archivable); 164 void UnarchiverLeaving(const BUnarchiver* archiver); 165 void Acquire(); 166 167 private: 168 status_t _ArchiveForToken(BMessage* archive, int32 token); 169 status_t _InstantiateObjectForToken(int32 token); 170 bool _InDestructor(); 171 void _EnterDestructor(); 172 173 ArchiveInfo* fObjects; 174 int32 fObjectCount; 175 std::stack<int32> fTokensInProgress; 176 int32 fRefcount; 177 }; 178 179 180 } // namespace Archiving 181 } // namespace BPrivate 182 183 #endif -
headers/os/app/Message.h
1 1 /* 2 * Copyright 2005-20 09, Haiku Inc. All Rights Reserved.2 * Copyright 2005-2010, Haiku Inc. All Rights Reserved. 3 3 * Distributed under the terms of the MIT License. 4 4 * 5 5 * Authors: … … 320 320 BMessage* fQueueLink; 321 321 // fQueueLink is used by BMessageQueue to build a linked list 322 322 323 uint32 fReserved[9];323 void* fArchivingPointer; 324 324 325 uint32 fReserved[8]; 326 325 327 // deprecated 326 328 BMessage(BMessage *message); 327 329 -
headers/private/app/MessagePrivate.h
1 1 /* 2 * Copyright 2005-20 09, Haiku Inc. All rights reserved.2 * Copyright 2005-2010, Haiku Inc. All rights reserved. 3 3 * Distributed under the terms of the MIT License. 4 4 * 5 5 * Authors: … … 13 13 #include <MessengerPrivate.h> 14 14 #include <TokenSpace.h> 15 15 16 17 16 #define MESSAGE_BODY_HASH_TABLE_SIZE 5 18 17 #define MAX_DATA_PREALLOCATION B_PAGE_SIZE * 10 19 18 #define MAX_FIELD_PREALLOCATION 50 … … 191 190 reply, sendTimeout, replyTimeout); 192 191 } 193 192 193 194 void*& 195 ArchivingPointer() 196 { 197 return fMessage->fArchivingPointer; 198 } 199 194 200 // static methods 195 201 196 202 static status_t