2012-11-17 4 views
1

précédemment mon programme utilisé pour sérialiser l'ensemble std::multimap<Participant*, Connection*> après qu'il a été complètement rempli. et c'était simple arc & _connections à la fois pour enregistrer et restaurer.boost serialization multimap manuellement

mais cela nécessite que chaque objet de connexion reste en mémoire. mais je n'ai pas besoin de ces objets pour autre chose que la sérialisation. Donc, pour minimiser la consommation de mémoire, il a décidé de sérialiser std::make_pair(connection->participant(), connection) dès leur création. et supprimer après la sérialisation est terminée.

La taille attendue de multimap est connue avant le début du remplissage.

Ce que je veux est de sérialisation manuellement ces paires de telle sorte que je ne ai pas besoin de modifier le code désérialisation qui simplement arc & _connections;

de boost/serialization/collections_save_imp.hpp Je vois

boost::serialization::save_construct_data_adl(
    ar, 
    &(*it), 
    boost::serialization::version<BOOST_DEDUCED_TYPENAME Container::value_type>::value 
); 
ar << boost::serialization::make_nvp("item", *it++); 

Alors dois-je besoin d'utiliser quelque chose comme

typedef std::pair<Participant*, Connection*> PairT; 

ar << BOOST_SERIALIZATION_NVP(expected_size); 

if(3 < ar.get_library_version()){// I don't really understand this magic number here 
    const unsigned int item_version = boost::serialization::version<PairT>::value; 
    ar << BOOST_SERIALIZATION_NVP(item_version); 
} 

PairT pair = std::make_pair(connection->participant(), connection); 
boost::serialization::save_construct_data_adl(
    ar, 
    pair, 
    boost::serialization::version<PairT>::value 
); 
ar << boost::serialization::make_nvp("item", pair); 
delete connection; 

Je ne sais pas exactement comment cela doit être fait. juste faire des suppositions.

Répondre

0

Je vois ce que vous essayez de faire mais je ne le recommanderais pas car il casse facilement. Si vous changez l'archive en XML par exemple, cela ne fonctionnera pas. Si vous effectuez une mise à niveau vers une version plus récente de , il se peut également qu'il se brise et qu'il soit difficile à déboguer. La raison en est que l'archive elle-même peut ajouter des données supplémentaires dans start_save() (l'ID de classe par exemple), puis fait la sérialisation réelle et se termine par un appel à end_save(). Comme ces méthodes sont protégées, vous ne pouvez pas les utiliser pour "simuler" la sérialisation de manière portable/stable.

Vous pouvez remplacer (spécialiser) la sérialisation multimap mais ce serait seulement vous donner accès au conteneur vide et que vous devez utiliser ruser (comme les variables globales) pour accéder à la connexion objets à sérialiser:

template<class Archive> 
inline void save(Archive& ar, const MultimapT& map, const unsigned version) { 
    Connection* p = new Connection(global_data->get(i)); 
} 

vous avez également désérialiser le même objet que vous sérialisation la seule façon propre est de donner l'archive un objet contenant le multimap qui traite de la sérialisation. Cet objet peut être la classe qui possède la carte ou un mannequin. Toutefois, cela nécessitera quelques modifications au code désérialisation existant:

ar << boost::serialization::make_nvp("map",Dummy(&_source)); 
// and 
ar >> boost::serialization::make_nvp("map",Dummy(&_connections)); 

Le constructeur du mannequin va prendre un pointeur sur l'objet nécessaire pour générer les connexions (lors de l'enregistrement) ou un pointeur vers la multimap (lors du chargement). La méthode save() du mannequin peut alors générer, stocker et supprimer des objets Connection à la volée tandis que la méthode load() remplit simplement le multimap.

Lorsque vous générez des objets à la volée, vous devez désactiver le suivi d'objets:

BOOST_CLASS_TRACKING(Connection, boost::serialization::track_never) 
BOOST_CLASS_TRACKING(Participant, boost::serialization::track_never) 

Sinon l'archive détecte que la même adresse mémoire est sérialisé à plusieurs reprises et créer des références au premier objet au lieu de stocker effectivement le Les données.

Voici un exemple de fonctions membres pour démontrer la sérialisation d'un objet contenant la multimap (classe fictive ou parent):

// class Foo { 

template<typename Archive> 
inline void save(Archive& ar, const unsigned version) const { 
    size_t count = expected_count(); 
    ar << BOOST_SERIALIZATION_NVP(count); 
    for(size_t i=0; i<count; ++i) { 
     Connection* connection = make_connection(i); 
     PairT pair(connection->participant(), connection); 
     ar << boost::serialization::make_nvp("item", pair); 
     delete connection; 
    } 
} 

template<typename Archive> 
inline void load(Archive& ar, const unsigned version) { 
    size_t count=0; 
    ar >> BOOST_SERIALIZATION_NVP(count); 
    while(count--) { 
     PairT pair; 
     ar >> boost::serialization::make_nvp("item", pair); 
     _connections->insert(pair); 
    } 
} 

friend boost::serialization::access; 
BOOST_SERIALIZATION_SPLIT_MEMBER() // split serialize() into save() and load() 
// } 

Références: intrusive/non-intrusive serialization, splitting save and load, object tracking

Questions connexes