Ticket #6256: archivable.patch

File archivable.patch, 23.2 KB (added by yourpalal, 14 years ago)

updated patch with fix for syntax error (oops, thanks luroh).

  • src/kits/support/Archivable.cpp

     
    11/*
    2  * Copyright (c) 2001-2008, Haiku, Inc.
     2 * Copyright (c) 2001-2010, Haiku, Inc.
    33 * Distributed under the terms of the MIT License.
    44 *
    55 * Authors:
    66 *      Erik Jaesler (erik@cgsoftware.com)
     7 *      Alex Wilson (yourpalal2@gmail.com)
    78 */
    89
    910/*! BArchivable mix-in class defines the archiving protocol.
     
    1314
    1415#include <ctype.h>
    1516#include <errno.h>
     17#include <new>
     18#include <set>
    1619#include <stdlib.h>
    1720#include <stdio.h>
    1821#include <string>
     
    2225
    2326#include <AppFileInfo.h>
    2427#include <Archivable.h>
     28#include <ArchivablePrivate.h>
    2529#include <Entry.h>
    2630#include <List.h>
    2731#include <OS.h>
     
    3337using std::string;
    3438using std::vector;
    3539
     40using namespace BPrivate::Archiving;
     41
    3642const char* B_CLASS_FIELD = "class";
    3743const char* B_ADD_ON_FIELD = "add_on";
    3844const int32 FUNC_NAME_LEN = 1024;
    3945
     46const char* kArchiveCountField = "_managed_archive_count";
     47
    4048// TODO: consider moving these to a separate module, and making them more
    4149//  full-featured (e.g., taking NS::ClassName::Function(Param p) instead
    4250//  of just NS::ClassName)
     
    209217
    210218BArchivable::BArchivable(BMessage* from)
    211219{
     220    if (BUnarchiver::ArchiveIsManaged(from)) {
     221        BUnarchiver::PrepareArchive(from);
     222        BUnarchiver(from).RegisterArchivable(this);
     223    }
    212224}
    213225
    214226
     
    225237        return B_BAD_VALUE;
    226238    }
    227239
     240    BArchiver::PrepareArchive(into);
     241    BArchiver(into).RegisterArchivable(this);
     242
    228243    BString name;
    229244    status_t status = demangle_class_name(typeid(*this).name(), name);
    230245    if (status != B_OK)
     
    250265}
    251266
    252267
    253 void BArchivable::_ReservedArchivable1() {}
    254 void BArchivable::_ReservedArchivable2() {}
    255 void BArchivable::_ReservedArchivable3() {}
     268status_t
     269BArchivable::AllUnarchived(const BMessage* archive)
     270{
     271    return B_OK;
     272}
    256273
     274// #pragma mark -
    257275
     276BArchiver::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
     286BArchiver::~BArchiver()
     287{
     288    fManager->ArchiverLeaving(this);   
     289}
     290
     291
     292status_t
     293BArchiver::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
     304bool
     305BArchiver::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
     318status_t
     319BArchiver::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
     328BMessage*
     329BArchiver::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
     339void
     340BArchiver::RegisterArchivable(const BArchivable* archivable)
     341{
     342    fManager->RegisterArchivable(archivable);
     343}
     344
     345
     346BArchiveManager*
     347BArchiver::_RetrieveManager(BMessage* archive)
     348{
     349    return BManagerBase::ArchiveManager(archive);
     350}
     351
     352
    258353// #pragma mark -
    259354
    260355
     356BUnarchiver::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
     368BUnarchiver::~BUnarchiver()
     369{
     370    if (fManager)
     371        fManager->UnarchiverLeaving(this);
     372}
     373
     374
     375status_t
     376BUnarchiver::FindArchivable(const char* name, BArchivable** archivable)
     377{
     378    return FindArchivable(name, 0, archivable);
     379}
     380
     381
     382status_t
     383BUnarchiver::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
     400status_t
     401BUnarchiver::EnsureUnarchived(const char* name, int32 index)
     402{
     403    BArchivable* retriever;
     404    return FindArchivable(name, index, &retriever);
     405}
     406
     407
     408const BMessage*
     409BUnarchiver::ArchiveMessage() const
     410{
     411    return fArchive;
     412}
     413
     414
     415bool
     416BUnarchiver::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
     431BMessage*
     432BUnarchiver::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
     446void
     447BUnarchiver::RegisterArchivable(BArchivable* archivable)
     448{
     449    _CallDebuggerIfManagerNull();
     450    fManager->RegisterArchivable(archivable);
     451}
     452
     453
     454BUnarchiveManager*
     455BUnarchiver::_RetrieveManager(BMessage* archive)
     456{
     457    return BManagerBase::UnarchiveManager(archive);
     458}
     459
     460
     461void
     462BUnarchiver::_CallDebuggerIfManagerNull()
     463{
     464    if (!fManager)
     465        debugger("BUnarchiver used with legacy or unprepared archive.");
     466}
     467
     468
     469// #pragma mark -
     470
     471
     472namespace {
     473    BString
     474    ArchiveFieldNameForToken(int32 token)
     475    {
     476        return BString("managed_archivable_") << token;
     477    }
     478}
     479
     480
     481// #pragma mark -
     482
     483
     484BArchiveManager*
     485BManagerBase::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
     499BUnarchiveManager*
     500BManagerBase::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
     519BArchiveManager::BArchiveManager(BMessage* topLevelArchive)
     520    :
     521    BManagerBase(topLevelArchive, BManagerBase::ARCHIVE_MANAGER),
     522    fTokenMap(),
     523    fPendingActions(20, true),
     524    fRefcount(0)
     525{
     526}
     527
     528
     529BArchiveManager::~BArchiveManager()
     530{
     531    _CompletePendingActions();
     532    fTopLevelArchive->AddInt32(kArchiveCountField, fTokenMap.size());
     533}
     534
     535
     536status_t
     537BArchiveManager::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
     553status_t
     554BArchiveManager::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
     570status_t
     571BArchiveManager::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
     586void
     587BArchiveManager::ArchiverLeaving(const BArchiver* archiver)
     588{
     589    if (--fRefcount == 0)
     590        delete this;
     591}
     592
     593
     594void
     595BArchiveManager::Acquire()
     596{
     597    fRefcount++;
     598}
     599
     600
     601void
     602BArchiveManager::RegisterArchivable(const BArchivable* archivable)
     603{
     604    if (fTokenMap.size() == 0)
     605        fTokenMap[archivable] = 0;
     606}
     607
     608
     609status_t
     610BArchiveManager::_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*/
     632bool
     633BArchiveManager::_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
     656void
     657BArchiveManager::_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
     692BUnarchiveManager::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
     711BUnarchiveManager::~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
     733status_t
     734BUnarchiveManager::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
     760void
     761BUnarchiveManager::RegisterArchivable(BArchivable* archivable)
     762{
     763    fObjects[fTokensInProgress.top()].archivable = archivable;
     764    fTokensInProgress.pop();
     765}
     766
     767
     768void
     769BUnarchiveManager::UnarchiverLeaving(const BUnarchiver* unarchiver)
     770{
     771    if (--fRefcount == 0)
     772        delete this;
     773}
     774
     775
     776void
     777BUnarchiveManager::Acquire()
     778{
     779    if (!_InDestructor())
     780        fRefcount++;
     781}
     782
     783
     784status_t
     785BUnarchiveManager::_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
     797status_t
     798BUnarchiveManager::_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
     809bool
     810BUnarchiveManager::_InDestructor()
     811{
     812    return (fRefcount < 0);
     813}
     814
     815
     816void
     817BUnarchiveManager::_EnterDestructor()
     818{
     819    fRefcount = -1;
     820}
     821
     822
     823// #pragma mark -
     824
     825
    261826BArchivable*
    262827instantiate_object(BMessage* archive, image_id* _id)
    263828{
     
    4751040    return find_instantiation_func(name, signature);
    4761041}
    4771042
     1043// BArchivable binary compatability
     1044#if __GNUC__ == 2
     1045
     1046// TODO: make sure this is the correct signature
     1047extern "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
     1056extern "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
     1065void BArchivable::_ReservedArchivable2() {}
     1066void BArchivable::_ReservedArchivable3() {}
     1067
     1068
  • headers/os/support/Archivable.h

     
    11/*
    2  * Copyright 2001-2007, Haiku, Inc. All Rights Reserved.
     2 * Copyright 2001-2010, Haiku, Inc. All Rights Reserved.
    33 * Distributed under the terms of the MIT License.
    44 */
    55#ifndef _ARCHIVABLE_H
     
    1212
    1313class BMessage;
    1414
     15namespace BPrivate {
     16namespace Archiving {
     17    class BArchiveManager;
     18    class BUnarchiveManager;
     19}
     20}
    1521
     22using BPrivate::Archiving::BArchiveManager;
     23using BPrivate::Archiving::BUnarchiveManager;
     24
     25
    1626class BArchivable {
    17     public:
    18         BArchivable(BMessage* from);
    19         BArchivable();
    20         virtual ~BArchivable();
     27public:
     28    BArchivable(BMessage* from);
     29    BArchivable();
     30    virtual ~BArchivable();
    2131
    22         virtual status_t Archive(BMessage* into, bool deep = true) const;
    23         static BArchivable* Instantiate(BMessage* archive);
     32    virtual status_t Archive(BMessage* into, bool deep = true) const;
     33    static BArchivable* Instantiate(BMessage* archive);
    2434
    25         // Private or reserved
    26         virtual status_t Perform(perform_code d, void* arg);
     35    virtual status_t Perform(perform_code d, void* arg);
    2736
    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);
    3244
    33         uint32 _reserved[2];
     45private:
     46    virtual void _ReservedArchivable2();
     47    virtual void _ReservedArchivable3();
     48
     49    uint32 _reserved[2];
    3450};
    3551
    3652
     53class BArchiver {
     54public:
     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);
     76private:
     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
     88class BUnarchiver {
     89public:
     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);
     106private:
     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
    37119// global functions
    38120
    39121typedef BArchivable* (*instantiation_func)(BMessage*);
    40122
    41 BArchivable* instantiate_object(BMessage *from, image_id *id);
    42 BArchivable* instantiate_object(BMessage *from);
     123BArchivable* instantiate_object(BMessage* from, image_id* id);
     124BArchivable* instantiate_object(BMessage* from);
    43125bool validate_instantiation(BMessage* from, const char* className);
    44126
    45127instantiation_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
     18namespace BPrivate {
     19namespace Archiving {
     20
     21
     22class BManagerBase {
     23public:
     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
     84protected:
     85    BMessage*       fTopLevelArchive;
     86    manager_type    fType;
     87};
     88
     89
     90struct 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
     107class BArchiveManager: public BManagerBase {
     108public:
     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
     125private:
     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
     138struct 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
     157class BUnarchiveManager: public BManagerBase {
     158public:
     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
     167private:
     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

     
    11/*
    2  * Copyright 2005-2009, Haiku Inc. All Rights Reserved.
     2 * Copyright 2005-2010, Haiku Inc. All Rights Reserved.
    33 * Distributed under the terms of the MIT License.
    44 *
    55 * Authors:
     
    320320        BMessage*       fQueueLink;
    321321            // fQueueLink is used by BMessageQueue to build a linked list
    322322
    323         uint32          fReserved[9];
     323        void*           fArchivingPointer;
    324324
     325        uint32          fReserved[8];
     326
    325327                        // deprecated
    326328                        BMessage(BMessage *message);
    327329
  • headers/private/app/MessagePrivate.h

     
    11/*
    2  * Copyright 2005-2009, Haiku Inc. All rights reserved.
     2 * Copyright 2005-2010, Haiku Inc. All rights reserved.
    33 * Distributed under the terms of the MIT License.
    44 *
    55 * Authors:
     
    1313#include <MessengerPrivate.h>
    1414#include <TokenSpace.h>
    1515
    16 
    1716#define MESSAGE_BODY_HASH_TABLE_SIZE    5
    1817#define MAX_DATA_PREALLOCATION          B_PAGE_SIZE * 10
    1918#define MAX_FIELD_PREALLOCATION         50
     
    191190                reply, sendTimeout, replyTimeout);
    192191        }
    193192
     193
     194        void*& 
     195        ArchivingPointer()
     196        {
     197            return fMessage->fArchivingPointer;
     198        }
     199
    194200        // static methods
    195201
    196202        static status_t