Patch by Alex Wilson (compilation fixes by myself): Extended the archiving/

unarchiving protocol to support archival of arbitrary object graphs.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@37431 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ingo Weinhold 2010-07-08 14:54:25 +00:00
parent 8fbd792dd8
commit e5150e2847
10 changed files with 990 additions and 29 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright 2005-2009, Haiku Inc. All Rights Reserved.
* Copyright 2005-2010, Haiku Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
@ -320,7 +320,9 @@ class BMessage {
BMessage* fQueueLink;
// fQueueLink is used by BMessageQueue to build a linked list
uint32 fReserved[9];
void* fArchivingPointer;
uint32 fReserved[8];
// deprecated
BMessage(BMessage *message);

View File

@ -1,5 +1,5 @@
/*
* Copyright 2001-2007, Haiku, Inc. All Rights Reserved.
* Copyright 2001-2010, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef _ARCHIVABLE_H
@ -12,25 +12,107 @@
class BMessage;
namespace BPrivate {
namespace Archiving {
class BArchiveManager;
class BUnarchiveManager;
}
}
using BPrivate::Archiving::BArchiveManager;
using BPrivate::Archiving::BUnarchiveManager;
class BArchivable {
public:
BArchivable(BMessage* from);
BArchivable();
virtual ~BArchivable();
public:
BArchivable(BMessage* from);
BArchivable();
virtual ~BArchivable();
virtual status_t Archive(BMessage* into, bool deep = true) const;
static BArchivable* Instantiate(BMessage* archive);
virtual status_t Archive(BMessage* into, bool deep = true) const;
static BArchivable* Instantiate(BMessage* archive);
// Private or reserved
virtual status_t Perform(perform_code d, void* arg);
virtual status_t Perform(perform_code d, void* arg);
private:
virtual void _ReservedArchivable1();
virtual void _ReservedArchivable2();
virtual void _ReservedArchivable3();
virtual status_t AllUnarchived(const BMessage* archive);
virtual status_t AllArchived(BMessage* archive) const;
uint32 _reserved[2];
private:
virtual void _ReservedArchivable3();
uint32 _reserved[2];
};
class BArchiver {
public:
BArchiver(BMessage* archive);
~BArchiver();
status_t AddArchivable(const char* name,
BArchivable* archivable, bool deep = true);
status_t GetTokenForArchivable(BArchivable* archivable,
int32& _token, bool deep = true);
bool IsArchived(BArchivable* archivable);
status_t Finish();
BMessage* ArchiveMessage() const;
private:
friend class BArchivable;
BArchiver(); // not defined
BArchiver(const BArchiver&); // not defined
void RegisterArchivable(const BArchivable* archivable);
BArchiveManager* fManager;
BMessage* fArchive;
bool fFinished;
};
class BUnarchiver {
public:
BUnarchiver(const BMessage* archive);
~BUnarchiver();
status_t GetArchivable(int32 token,
BArchivable** archivable);
status_t FindArchivable(const char* name,
BArchivable** archivable);
status_t FindArchivable(const char* name, int32 index,
BArchivable** archivable);
status_t EnsureUnarchived(const char* name,
int32 index = 0);
status_t EnsureUnarchived(int32 token);
bool IsInstantiated(int32 token);
bool IsInstantiated(const char* name,
int32 index = 0);
status_t Finish();
const BMessage* ArchiveMessage() const;
static bool IsArchiveManaged(BMessage* archive);
static BMessage* PrepareArchive(BMessage*& archive);
private:
friend class BArchivable;
BUnarchiver(); // not defined
BUnarchiver(const BUnarchiver&); // not defined
void RegisterArchivable(BArchivable* archivable);
void _CallDebuggerIfManagerNull();
BUnarchiveManager* fManager;
const BMessage* fArchive;
bool fFinished;
};
@ -38,8 +120,8 @@ class BArchivable {
typedef BArchivable* (*instantiation_func)(BMessage*);
BArchivable* instantiate_object(BMessage *from, image_id *id);
BArchivable* instantiate_object(BMessage *from);
BArchivable* instantiate_object(BMessage* from, image_id* id);
BArchivable* instantiate_object(BMessage* from);
bool validate_instantiation(BMessage* from, const char* className);
instantiation_func find_instantiation_func(const char* className,

View File

@ -1,5 +1,5 @@
/*
* Copyright 2005-2009, Haiku Inc. All rights reserved.
* Copyright 2005-2010, Haiku Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
@ -191,6 +191,20 @@ class BMessage::Private {
reply, sendTimeout, replyTimeout);
}
void*
ArchivingPointer()
{
return fMessage->fArchivingPointer;
}
void
SetArchivingPointer(void* pointer)
{
fMessage->fArchivingPointer = pointer;
}
// static methods
static status_t

View File

@ -21,9 +21,12 @@ enum {
PERFORM_CODE_SET_LAYOUT = 1006,
PERFORM_CODE_INVALIDATE_LAYOUT = 1007,
PERFORM_CODE_DO_LAYOUT = 1008,
PERFORM_CODE_GET_TOOL_TIP_AT = 1009
PERFORM_CODE_GET_TOOL_TIP_AT = 1009,
// support kit
PERFORM_CODE_ALL_ARCHIVED = 1010,
PERFORM_CODE_ALL_UNARCHIVED = 1011
};

View File

@ -0,0 +1,23 @@
/*
* Copyright 2010, Haiku, Inc.
* Distributed under the terms of the MIT License.
*/
#ifndef _BINARY_COMPATIBILITY_SUPPORT_H
#define _BINARY_COMPATIBILITY_SUPPORT_H
#include <binary_compatibility/Global.h>
struct perform_data_all_unarchived {
const BMessage* archive;
status_t return_value;
};
struct perform_data_all_archived {
BMessage* archive;
status_t return_value;
};
#endif /* _BINARY_COMPATIBILITY_INTERFACE_H_ */

View File

@ -1,5 +1,5 @@
/*
* Copyright 2005-2009, Haiku Inc. All rights reserved.
* Copyright 2005-2010, Haiku Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
@ -333,6 +333,8 @@ BMessage::_InitCommon(bool initHeader)
fOriginal = NULL;
fQueueLink = NULL;
fArchivingPointer = NULL;
if (initHeader)
return _InitHeader();
@ -394,6 +396,8 @@ BMessage::_Clear()
free(fData);
fData = NULL;
fArchivingPointer = NULL;
fFieldsAvailable = 0;
fDataAvailable = 0;

View File

@ -1,9 +1,10 @@
/*
* Copyright (c) 2001-2008, Haiku, Inc.
* Copyright (c) 2001-2010, Haiku, Inc.
* Distributed under the terms of the MIT License.
*
* Authors:
* Erik Jaesler (erik@cgsoftware.com)
* Alex Wilson (yourpalal2@gmail.com)
*/
/*! BArchivable mix-in class defines the archiving protocol.
@ -29,10 +30,16 @@
#include <Roster.h>
#include <String.h>
#include <binary_compatibility/Support.h>
#include "ArchivingManagers.h"
using std::string;
using std::vector;
using namespace BPrivate::Archiving;
const char* B_CLASS_FIELD = "class";
const char* B_ADD_ON_FIELD = "add_on";
const int32 FUNC_NAME_LEN = 1024;
@ -61,7 +68,7 @@ demangle_class_name(const char* name, BString& out)
namespaceCount = strtoul(name, (char**)&name, 10);
if (name[0] != '_')
return B_BAD_VALUE;
return B_BAD_VALUE;
} else
namespaceCount = name[0] - '0';
@ -69,7 +76,7 @@ demangle_class_name(const char* name, BString& out)
for (int i = 0; i < namespaceCount - 1; i++) {
if (!isdigit(name[0]))
return B_BAD_VALUE;
return B_BAD_VALUE;
int nameLength = strtoul(name, (char**)&name, 10);
out.Append(name, nameLength);
@ -209,6 +216,10 @@ BArchivable::BArchivable()
BArchivable::BArchivable(BMessage* from)
{
if (BUnarchiver::IsArchiveManaged(from)) {
BUnarchiver::PrepareArchive(from);
BUnarchiver(from).RegisterArchivable(this);
}
}
@ -225,6 +236,9 @@ BArchivable::Archive(BMessage* into, bool deep) const
return B_BAD_VALUE;
}
if (BManagerBase::ArchiveManager(into))
BArchiver(into).RegisterArchivable(this);
BString name;
status_t status = demangle_class_name(typeid(*this).name(), name);
if (status != B_OK)
@ -245,14 +259,269 @@ BArchivable::Instantiate(BMessage* from)
status_t
BArchivable::Perform(perform_code d, void* arg)
{
// TODO: Check against original
return B_ERROR;
switch (d) {
case PERFORM_CODE_ALL_UNARCHIVED:
{
perform_data_all_unarchived* data =
(perform_data_all_unarchived*)arg;
data->return_value = BArchivable::AllUnarchived(data->archive);
return B_OK;
}
case PERFORM_CODE_ALL_ARCHIVED:
{
perform_data_all_archived* data =
(perform_data_all_archived*)arg;
data->return_value = BArchivable::AllArchived(data->archive);
return B_OK;
}
}
return B_NAME_NOT_FOUND;
}
void BArchivable::_ReservedArchivable1() {}
void BArchivable::_ReservedArchivable2() {}
void BArchivable::_ReservedArchivable3() {}
status_t
BArchivable::AllUnarchived(const BMessage* archive)
{
return B_OK;
}
status_t
BArchivable::AllArchived(BMessage* archive) const
{
return B_OK;
}
// #pragma mark -
BArchiver::BArchiver(BMessage* archive)
:
fManager(BManagerBase::ArchiveManager(archive)),
fArchive(archive),
fFinished(false)
{
if (!fManager)
fManager = new BArchiveManager(this);
}
BArchiver::~BArchiver()
{
if (!fFinished)
fManager->ArchiverLeaving(this);
}
status_t
BArchiver::AddArchivable(const char* name, BArchivable* archivable, bool deep)
{
int32 token;
status_t err = GetTokenForArchivable(archivable, token, deep);
if (err != B_OK)
return err;
return fArchive->AddInt32(name, token);
}
status_t
BArchiver::GetTokenForArchivable(BArchivable* archivable,
int32& _token, bool deep)
{
status_t err = B_OK;
if (!IsArchived(archivable))
err = fManager->ArchiveObject(archivable, deep);
if (err == B_OK)
return fManager->GetTokenForArchivable(archivable, _token);
return err;
}
bool
BArchiver::IsArchived(BArchivable* archivable)
{
return fManager->IsArchived(archivable);
}
status_t
BArchiver::Finish()
{
if (fFinished)
debugger("Finish() called multiple times on same BArchiver.");
fFinished = true;
return fManager->ArchiverLeaving(this);
}
BMessage*
BArchiver::ArchiveMessage() const
{
return fArchive;
}
void
BArchiver::RegisterArchivable(const BArchivable* archivable)
{
fManager->RegisterArchivable(archivable);
}
// #pragma mark -
BUnarchiver::BUnarchiver(const BMessage* archive)
:
fManager(BManagerBase::UnarchiveManager(archive)),
fArchive(archive),
fFinished(false)
{
}
BUnarchiver::~BUnarchiver()
{
if (!fFinished && fManager)
fManager->UnarchiverLeaving(this);
}
status_t
BUnarchiver::GetArchivable(int32 token, BArchivable** archivable)
{
_CallDebuggerIfManagerNull();
if (archivable == NULL)
return B_BAD_VALUE;
return fManager->ArchivableForToken(archivable, token);
}
status_t
BUnarchiver::FindArchivable(const char* name, BArchivable** archivable)
{
return FindArchivable(name, 0, archivable);
}
status_t
BUnarchiver::FindArchivable(const char* name,
int32 index, BArchivable** archivable)
{
int32 token;
status_t err = fArchive->FindInt32(name, index, &token);
if (err != B_OK)
return err;
return GetArchivable(token, archivable);
}
status_t
BUnarchiver::EnsureUnarchived(const char* name, int32 index)
{
BArchivable* dummy;
return FindArchivable(name, index, &dummy);
}
status_t
BUnarchiver::EnsureUnarchived(int32 token)
{
BArchivable* dummy;
return GetArchivable(token, &dummy);
}
bool
BUnarchiver::IsInstantiated(int32 token)
{
return fManager->IsInstantiated(token);
}
bool
BUnarchiver::IsInstantiated(const char* field, int32 index)
{
int32 token;
if (fArchive->FindInt32(field, index, &token) == B_OK)
return IsInstantiated(token);
return false;
}
status_t
BUnarchiver::Finish()
{
if (fFinished)
debugger("Finish() called multiple times on same BArchiver.");
fFinished = true;
return fManager->UnarchiverLeaving(this);
}
const BMessage*
BUnarchiver::ArchiveMessage() const
{
return fArchive;
}
bool
BUnarchiver::IsArchiveManaged(BMessage* archive)
{
// managed child archives will return here
if (BManagerBase::ManagerPointer(archive))
return true;
// managed top level archives return here
int32 dummy;
if (archive->FindInt32(kArchiveCountField, &dummy) == B_OK)
return true;
return false;
}
BMessage*
BUnarchiver::PrepareArchive(BMessage*& archive)
{
// this check allows PrepareArchive to be
// called on new or old-style archives
if (BUnarchiver::IsArchiveManaged(archive)) {
BUnarchiveManager* manager = BManagerBase::UnarchiveManager(archive);
if (!manager)
manager = new BUnarchiveManager(archive);
manager->Acquire();
}
return archive;
}
void
BUnarchiver::RegisterArchivable(BArchivable* archivable)
{
_CallDebuggerIfManagerNull();
fManager->RegisterArchivable(archivable);
}
void
BUnarchiver::_CallDebuggerIfManagerNull()
{
if (!fManager)
debugger("BUnarchiver used with legacy or unprepared archive.");
}
// #pragma mark -
@ -475,3 +744,61 @@ find_instantiation_func(BMessage* archive)
return find_instantiation_func(name, signature);
}
// BArchivable binary compatability
#if __GNUC__ == 2
extern "C" status_t
_ReservedArchivable1__11BArchivable(BArchivable* archivable,
const BMessage* archive)
{
// AllUnarchived
perform_data_all_unarchived performData;
performData.archive = archive;
archivable->Perform(PERFORM_CODE_ALL_UNARCHIVED, &performData);
return performData.return_value;
}
extern "C" status_t
_ReservedArchivable2__11BArchivable(BArchivable* archivable,
BMessage* archive)
{
// AllArchived
perform_data_all_archived performData;
performData.archive = archive;
archivable->Perform(PERFORM_CODE_ALL_ARCHIVED, &performData);
return performData.return_value;
}
#elif __GNUC__ > 2
extern "C" status_t
_ZN11BArchivable20_ReservedArchivable1Ev(BArchivable* archivable,
const BMessage* archive)
{
// AllUnarchived
perform_data_all_unarchived performData;
performData.archive = archive;
archivable->Perform(PERFORM_CODE_ALL_UNARCHIVED, &performData);
return performData.return_value;
}
extern "C" status_t
_ZN11BArchivable20_ReservedArchivable2Ev(BArchivable* archivable,
BMessage* archive)
{
// AllArchived
perform_data_all_archived performData;
performData.archive = archive;
archivable->Perform(PERFORM_CODE_ALL_ARCHIVED, &performData);
return performData.return_value;
}
#endif // _GNUC__ > 2
void BArchivable::_ReservedArchivable3() {}

View File

@ -0,0 +1,355 @@
/*
* Copyright (c) 2010, Haiku, Inc.
* Distributed under the terms of the MIT License.
*
* Authors:
* Alex Wilson (yourpalal2@gmail.com)
*/
#include <syslog.h>
#include <typeinfo>
#include "ArchivingManagers.h"
namespace BPrivate {
namespace Archiving {
const char* kArchiveCountField = "_managed_archive_count";
const char* kArchivableField = "_managed_archivable";
const char* kTokenField = "_managed_token";
} }
using namespace BPrivate::Archiving;
BArchiveManager*
BManagerBase::ArchiveManager(const BMessage* archive)
{
BManagerBase* manager = ManagerPointer(archive);
if (!manager)
return NULL;
if (manager->fType == ARCHIVE_MANAGER)
return static_cast<BArchiveManager*>(manager);
debugger("Overlapping managed unarchive/archive sessions.");
return NULL;
}
BUnarchiveManager*
BManagerBase::UnarchiveManager(const BMessage* archive)
{
BManagerBase* manager = ManagerPointer(archive);
if (!manager)
return NULL;
if (manager->fType == UNARCHIVE_MANAGER)
return static_cast<BUnarchiveManager*>(manager);
debugger("More calls to BUnarchiver::PrepareMessage()"
" than BUnarchivers created.");
return NULL;
}
// #pragma mark -
struct BArchiveManager::ArchiveInfo {
ArchiveInfo()
:
token(-1),
archive(NULL)
{
}
~ArchiveInfo()
{
delete archive;
}
int32 token;
BMessage* archive;
};
BArchiveManager::BArchiveManager(const BArchiver* creator)
:
BManagerBase(creator->ArchiveMessage(), BManagerBase::ARCHIVE_MANAGER),
fTokenMap(),
fCreator(creator)
{
}
BArchiveManager::~BArchiveManager()
{
fTopLevelArchive->AddInt32(kArchiveCountField, fTokenMap.size());
}
status_t
BArchiveManager::GetTokenForArchivable(BArchivable* archivable, int32& _token)
{
if (!archivable) {
_token = -42;
return B_OK;
}
TokenMap::iterator it = fTokenMap.find(archivable);
if (it == fTokenMap.end())
return B_ENTRY_NOT_FOUND;
_token = it->second.token;
return B_OK;
}
status_t
BArchiveManager::ArchiveObject(BArchivable* archivable, bool deep)
{
if (IsArchived(archivable)){
debugger("BArchivable requested to be archived"
" was previously archived.");
}
ArchiveInfo& info = fTokenMap[archivable];
info.archive = new BMessage();
info.token = fTokenMap.size() - 1;
MarkArchive(info.archive);
status_t err = archivable->Archive(info.archive, deep);
if (err != B_OK)
fTokenMap.erase(archivable);
// info.archive gets deleted here
return err;
}
bool
BArchiveManager::IsArchived(BArchivable* archivable)
{
if (!archivable)
return true;
return (fTokenMap.find(archivable) != fTokenMap.end());
}
status_t
BArchiveManager::ArchiverLeaving(const BArchiver* archiver)
{
if (archiver == fCreator) {
// first, we must sort the objects into the order they were archived in
typedef std::pair<BMessage*, const BArchivable*> archivePair ;
archivePair pairs[fTokenMap.size()];
for(TokenMap::iterator it = fTokenMap.begin(), end = fTokenMap.end();
it != end; it++) {
ArchiveInfo& info = it->second;
pairs[info.token].first = info.archive;
pairs[info.token].second = it->first;
// make sure fTopLevelArchive isn't deleted
if (info.archive == fTopLevelArchive)
info.archive = NULL;
}
status_t err = B_ERROR;
int32 count = fTokenMap.size();
for (int32 i = 0; i < count; i++) {
const archivePair& pair = pairs[i];
err = pair.second->AllArchived(pair.first);
if (err == B_OK && i > 0) {
err = fTopLevelArchive->AddMessage(kArchivableField,
pair.first);
}
if (err != B_OK) {
syslog(LOG_ERR, "AllArchived failed for object of type %s.",
typeid(*pairs[i].second).name());
break;
}
}
delete this;
return err;
}
return B_OK;
}
void
BArchiveManager::RegisterArchivable(const BArchivable* archivable)
{
if (fTokenMap.size() == 0) {
ArchiveInfo& info = fTokenMap[archivable];
info.archive = fTopLevelArchive;
info.token = 0;
}
}
// #pragma mark -
struct BUnarchiveManager::ArchiveInfo {
ArchiveInfo()
:
archivable(NULL),
archive()
{
}
bool
operator<(const ArchiveInfo& other)
{
return archivable < other.archivable;
}
BArchivable* archivable;
BMessage archive;
};
// #pragma mark -
BUnarchiveManager::BUnarchiveManager(BMessage* archive)
:
BManagerBase(archive, BManagerBase::UNARCHIVE_MANAGER),
fObjects(NULL),
fObjectCount(0),
fTokenInProgress(0),
fRefCount(0)
{
archive->FindInt32(kArchiveCountField, &fObjectCount);
fObjects = new ArchiveInfo[fObjectCount];
// fObjects[0] is a placeholder for the object that started
// this unarchiving session.
for (int32 i = 0; i < fObjectCount - 1; i++) {
BMessage* into = &fObjects[i + 1].archive;
status_t err = archive->FindMessage(kArchivableField, i, into);
MarkArchive(into);
if (err != B_OK)
syslog(LOG_ERR, "Failed to find managed archivable");
}
}
BUnarchiveManager::~BUnarchiveManager()
{
delete[] fObjects;
}
status_t
BUnarchiveManager::ArchivableForToken(BArchivable** _archivable, int32 token)
{
if (!_archivable || token > fObjectCount)
return B_BAD_VALUE;
if (token < 0) {
*_archivable = NULL;
return B_OK;
}
status_t err = B_OK;
if (!fObjects[token].archivable) {
if (fRefCount > 0)
err = _InstantiateObjectForToken(token);
else {
syslog(LOG_ERR, "Object requested from AllUnarchived()"
" was not previously instantiated");
err = B_ERROR;
}
}
*_archivable = fObjects[token].archivable;
return err;
}
bool
BUnarchiveManager::IsInstantiated(int32 token)
{
if (token < 0 || token >= fObjectCount)
return false;
return fObjects[token].archivable;
}
void
BUnarchiveManager::RegisterArchivable(BArchivable* archivable)
{
if (!archivable)
debugger("Cannot register NULL pointer");
fObjects[fTokenInProgress].archivable = archivable;
}
status_t
BUnarchiveManager::UnarchiverLeaving(const BUnarchiver* unarchiver)
{
if (--fRefCount == 0) {
fRefCount = -1;
// make sure we de not end up here again!
BArchivable* archivable = fObjects[0].archivable;
status_t err = archivable->AllUnarchived(fTopLevelArchive);
for (int32 i = 1; i < fObjectCount; i++) {
if (err != B_OK)
break;
archivable = fObjects[i].archivable;
err = archivable->AllUnarchived(&fObjects[i].archive);
}
if (err != B_OK) {
syslog(LOG_ERR, "AllUnarchived failed for object of type %s.",
typeid(*archivable).name());
}
delete this;
return err;
}
return B_OK;
}
void
BUnarchiveManager::Acquire()
{
if (fRefCount >= 0)
fRefCount++;
}
status_t
BUnarchiveManager::_InstantiateObjectForToken(int32 token)
{
fTokenInProgress = token;
if(!instantiate_object(&fObjects[token].archive))
return B_ERROR;
return B_OK;
}

View File

@ -0,0 +1,150 @@
/*
* Copyright 2010, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef _ARCHIVING_MANAGERS_H
#define _ARCHIVING_MANAGERS_H
#include <map>
#include <String.h>
#include <ObjectList.h>
#include <MessagePrivate.h>
#include <Archivable.h>
namespace BPrivate {
namespace Archiving {
extern const char* kArchiveCountField;
extern const char* kArchivableField;
extern const char* kTokenField;
class BManagerBase {
public:
enum manager_type {
ARCHIVE_MANAGER,
UNARCHIVE_MANAGER
};
BManagerBase(BMessage* topLevelArchive, manager_type type)
:
fTopLevelArchive(topLevelArchive),
fType(type)
{
MarkArchive(topLevelArchive);
}
static BManagerBase*
ManagerPointer(const BMessage* constArchive)
{
BMessage* archive = const_cast<BMessage*>(constArchive);
return static_cast<BManagerBase*>(
BMessage::Private(archive).ArchivingPointer());
}
static void
SetManagerPointer(BMessage* archive, BManagerBase* manager)
{
BMessage::Private(archive).SetArchivingPointer(manager);
}
void
MarkArchive(BMessage* archive)
{
BManagerBase* manager = ManagerPointer(archive);
if (manager != NULL)
debugger("Overlapping managed archiving/unarchiving sessions!");
SetManagerPointer(archive, this);
}
void
UnmarkArchive(BMessage* archive)
{
BManagerBase* manager = ManagerPointer(archive);
if (manager == this)
SetManagerPointer(archive, NULL);
else
debugger("Overlapping managed archiving/unarchiving sessions!");
}
static BArchiveManager* ArchiveManager(const BMessage* archive);
static BUnarchiveManager* UnarchiveManager(const BMessage* archive);
protected:
~BManagerBase()
{
UnmarkArchive(fTopLevelArchive);
}
BMessage* fTopLevelArchive;
manager_type fType;
};
class BArchiveManager: public BManagerBase {
public:
BArchiveManager(const BArchiver* creator);
status_t GetTokenForArchivable(BArchivable* archivable,
int32& _token);
status_t ArchiveObject(BArchivable* archivable, bool deep);
bool IsArchived(BArchivable* archivable);
status_t ArchiverLeaving(const BArchiver* archiver);
void Acquire();
void RegisterArchivable(const BArchivable* archivable);
private:
~BArchiveManager();
struct ArchiveInfo;
typedef std::map<const BArchivable*, ArchiveInfo> TokenMap;
TokenMap fTokenMap;
const BArchiver* fCreator;
};
class BUnarchiveManager: public BManagerBase {
public:
BUnarchiveManager(BMessage* topLevelArchive);
status_t ArchivableForToken(BArchivable** archivable,
int32 token);
bool IsInstantiated(int32 token);
void RegisterArchivable(BArchivable* archivable);
status_t UnarchiverLeaving(const BUnarchiver* archiver);
void Acquire();
private:
~BUnarchiveManager();
status_t _ExtractArchiveAt(int32 index);
status_t _InstantiateObjectForToken(int32 token);
struct ArchiveInfo;
ArchiveInfo* fObjects;
int32 fObjectCount;
int32 fTokenInProgress;
int32 fRefCount;
};
} // namespace Archiving
} // namespace BPrivate
#endif

View File

@ -6,6 +6,7 @@ UsePrivateHeaders app interface media shared support ;
MergeObject <libbe>support_kit.o :
Archivable.cpp
ArchivingManagers.cpp
Beep.cpp
BlockCache.cpp
ByteOrder.cpp