увеличить сериализацию мультикарты вручную

Ранее моя программа использовалась для сериализации всего std::multimap<Participant*, Connection*> после того, как он был полностью заселен. и это было просто arc & _connections для сохранения и восстановления.

но для этого нужно, чтобы каждый объект соединения оставался в памяти. но мне не нужны эти объекты для чего-либо другого, кроме сериализации. Поэтому, чтобы минимизировать потребление памяти, его решили сериализовать std::make_pair(connection->participant(), connection) как только они будут созданы. и удалить после завершения сериализации.

ожидаемый размер мультикарты известен до начала заполнения.

Я хочу вручную сериализовать эти пары так, чтобы мне не нужно было изменять код десериализации, который просто arc & _connections;

от boost/serialization/collections_save_imp.hpp я вижу

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++);

Так что мне нужно использовать что-то вроде

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;

Я не уверен точно, как это должно быть сделано. просто гадать.

1

Решение

Я вижу, что вы пытаетесь сделать, но я бы не рекомендовал это, потому что это легко сломалось.
Например, если вы измените архив на xml, он не будет работать. Если вы обновитесь до более новой версии
версия boost, она также может сломаться и ее будет сложно отладить. Причина в том, что
сам архив может добавить некоторые дополнительные данные в start_save() (идентификатор класса, например), то это
выполняет фактическую сериализацию и заканчивает вызовом end_save(), Поскольку эти методы
защищены, вы не можете использовать их для «подделки» сериализации в переносимом / стабильном режиме.

Вы можете переопределить (специализировать) сериализацию мультикарты, но это только даст вам доступ к
пустой контейнер, и вам придется использовать некоторые хитрости (например, глобальные переменные) для доступа к соединению
объекты, которые вы хотите сериализовать:

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

Вы также должны десериализовать тот же объект, который вы сериализуете, поэтому единственный чистый способ — предоставить архиву объект, содержащий мультикарту, которая имеет дело с сериализацией. Этим объектом может быть либо класс, которому принадлежит карта, либо фиктивный объект. Однако это потребует некоторых изменений в существующем коде десериализации:

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

Конструктор манекена возьмет указатель на объект, необходимый для генерации соединений.
(при сохранении) или указатель на мультикарту (при загрузке). Манекен save() метод может генерировать,
сохранять и удалять объекты подключения на лету, пока load() Метод просто заполняет мультикарту.

Когда вы генерируете объекты на лету, вы должны отключить отслеживание объектов:

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

В противном случае архив обнаруживает, что один и тот же адрес памяти многократно сериализуется, и создает ссылки на первый объект вместо фактического хранения данных.

Вот пример функций-членов, демонстрирующих сериализацию объекта, содержащего мультикарту (фиктивный или родительский класс):

// 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()
// }

Рекомендации: навязчивая / неинтрузивная сериализация, разделение сохранить и загрузить, отслеживание объекта

0

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]