2015-03-09 1 views
1

Я пытаюсь повысить :: сериализует структуры, которые указывают на объекты (скажем, класса символов), реализующие идею одного экземпляра за уникальность - < что-то > , Это значит, что эти объекты создаются не напрямую, а с использованием символа статического метода :: get(). Этот метод извлекает существующий объект из некоторого глобального словаря или при необходимости создает новый объект.boost :: сериализация одного экземпляра на уникальный идентификатор

Теперь сложная часть заключается в том, что в моей системе у меня много больших структур с указателями на такие символы. В то же время структуры не подходят всем в памяти. Поэтому мне нужно последовательно строить, готовить и сериализовать каждую из структур отдельно. Позже я буду deserialize и обрабатывать структуры по запросу.

Стандартные методы boost :: serialize, а именно load (...) и save (...) здесь не работают. Наверху десериализация структуры потеряла бы общесистемную уникальность символов, и сериализация бы потратила много места (объекты моего символа довольно велики). Я прочитал документы повышения и обнаружил, что для нестандартных конструкторов я могу использовать функции save_construct_data и load_construct_data. Но, по словам документа, по умолчанию load_construct_data «просто использует конструктор по умолчанию для инициализации ранее выделенной памяти». Так снова это не так.

Вопрос в следующем: как я могу обойти эту функцию загрузки, чтобы я мог избежать выделения и использовать мой символ :: get() вместо этого? Или, может быть, есть более элегантное решение?

EDIT: прилагается простой код, демонстрирующий проблему.

struct structure_element { 
}; 

class symbol : public structure_element { 
    symbol(string x); 
    map<string, symbol> known_symbols; 
public: 
    static symbol *get(string x) { 
    if (known_symbols.find(x) != known.symbols.end()){ 
     known_symbols[x] = symbol(x); 
    } 
    return &known_symbols[x]; 
    } 
} 

class structure_node : public structure_element { 
    set<symbol *> some_attributes; 
    vector<structure_element *> children; 
} 

ответ

0

В общем, исключительные случаи могут реализоватьload_construct_data (очевидно, это означает, что вы не полагаться на реализацию по умолчанию, как вы уже заметили в вашем вопросе).

В частности: используйте Boost Flyweight. Или посмотрите, как они implemented serialization для вдохновения.

Без конкретной программы-образца я не могу продемонстрировать вам ничего.

Заполнение некоторых из заготовок, вот демонстрационная программа, которая должна дать почувствовать вещи:

#include <iostream> 
#include <boost/archive/text_oarchive.hpp> 
#include <boost/serialization/string.hpp> 
#include <boost/serialization/vector.hpp> 
#include <boost/serialization/set.hpp> 
#include <boost/serialization/map.hpp> 

#if 0 
# define DEMO_FLYWEIGHT 
# include <boost/flyweight/serialize.hpp> 
# include <boost/flyweight.hpp> 
#endif 

struct structure_element { 
    virtual ~structure_element() {} 

    private: 
    friend class boost::serialization::access; 
    template <typename Ar> void serialize(Ar& /*ar*/, unsigned /*version*/) { 
    } 
}; 

namespace detail { 
    struct symbol_impl { 
     symbol_impl(std::string const& x) : _x(x) { } 

#ifdef DEMO_FLYWEIGHT 
     size_t hash() const { return boost::hash_value(_x); } 
     //bool operator< (symbol_impl const& other) const { return _x < other._x; } 
     bool operator==(symbol_impl const& other) const { return _x == other._x; } 
#endif 

     private: 
     std::string _x; 

     friend class boost::serialization::access; 
     template <typename Ar> void serialize(Ar& ar, unsigned /*version*/) { 
      ar & _x; 
     } 
    }; 
} 

#ifdef DEMO_FLYWEIGHT 
namespace boost { 
    template <> struct hash<::detail::symbol_impl> { 
     size_t operator()(::detail::symbol_impl const& s) const { return s.hash(); } 
    }; 
} 
#endif 

struct symbol : public structure_element { 
    symbol(std::string const& x) : _impl(x) {} 

    private: 
#ifdef DEMO_FLYWEIGHT 
    boost::flyweight<detail::symbol_impl> _impl; 
#else 
    detail::symbol_impl _impl; 
#endif 

    friend class boost::serialization::access; 
    template <typename Ar> void serialize(Ar& ar, unsigned /*version*/) { 
     ar & boost::serialization::base_object<structure_element>(*this); 
     ar & _impl; 
    } 
}; 

struct structure_node : public structure_element { 
    structure_node(std::set<symbol*> a, std::vector<structure_element*> c) 
     : some_attributes(std::move(a)), children(std::move(c)) 
    { 
    } 

    // TODO value semantics/ownership 
    private: 
    std::set<symbol *> some_attributes; 
    std::vector<structure_element *> children; 

    friend class boost::serialization::access; 
    template <typename Ar> void serialize(Ar& ar, unsigned /*version*/) { 
     ar & boost::serialization::base_object<structure_element>(*this); 
     ar & some_attributes; 
     ar & children; 
    } 
}; 

#include <boost/make_shared.hpp> 

int main() { 
    // everything is leaked, by design 
    symbol* bar = new symbol("bar"); 

    structure_node data { 
     { 
      new symbol("foo"), 
      bar, 
      new symbol("foo"), 
      new symbol("foo"), 
      bar, 
     }, 
     { 
      bar, 
     } 
    }; 

    boost::archive::text_oarchive oa(std::cout); 
    oa << data; 
} 

Примечания:

  • Live On Coliruбез мухи

    22 serialization::archive 11 0 0 1 0 
    0 0 0 4 0 3 1 0 
    1 
    2 0 0 3 bar 3 
    3 
    4 3 foo 3 
    5 
    6 3 foo 3 
    7 
    8 3 foo 0 0 1 0 3 1 
    
  • Live On Coliruс балансира включен

    22 serialization::archive 11 0 0 1 0 
    0 0 0 4 0 3 1 0 
    1 
    2 0 0 0 0 0 3 bar 3 
    3 
    4 1 3 foo 3 
    5 
    6 1 3 
    7 
    8 1 0 0 1 0 3 1 
    

Обратите внимание, как объекты уже отслеживаются при сериализации с помощью указателя.Это означает, что никакие дубликаты не сериализуются, даже если они не используют мухи, см., Например, bar объект используется 3 раз.

Для объекта foo вы можете увидеть, что его реализация «дедуплицирована», если вы будете использовать мухи.

Boost Flyweight может быть сконфигурирован и может быть выполнен так, чтобы выполняться значительно лучше, чем по умолчанию. Я имею в виду библиотечную документацию, если вы хотите узнать больше

+0

Я прикрепил образец. Спасибо, что указали «мухи», я не знал этого имени шаблона. Кратко посмотрите на boost :: flyweight показывает, что это более или менее то, что мне нужно, но мне нужно как-то поместить flyweight в мою иерархию классов (ранее я не упоминал об этом аспекте, извините). Я хотел бы услышать ваш подробный комментарий. – bzaborow

+0

@bzaborow и у вас есть – sehe

 Смежные вопросы

  • Нет связанных вопросов^_^