每个唯一ID的boost :: serialization一个实例

时间:2015-03-09 02:16:12

标签: c++ serialization boost-serialization

我正在尝试提升:: serialize结构,这些结构指向对象(比如符号类),实现单实例每个唯一的概念< something>。这意味着,这些对象不是直接创建的,而是使用静态方法符号:: get()。此方法从某个全局字典中检索现有对象,或者在必要时创建新对象。

现在困难的是,在我的系统中,我有许多大型结构,指向这些符号。结构不能同时适合所有内存。所以我需要分别按顺序构建,预处理和序列化每个结构。稍后我会根据请求反序列化和处理结构。

标准的boost :: serialize方法,即load(...)和save(...)在这里不起作用。结构的Uppon反序列化将失去符号的系统范围的唯一性,并且序列化将浪费大量空间(我的符号对象非常大)。我已经阅读了boost文档,发现对于非标准构造函数,我可以使用save_construct_data和load_construct_data函数。但文档也说,默认的load_construct_data“只使用默认构造函数初始化以前分配的内存”。所以这不是它。

问题是:如何绕过这个加载函数,以便我可以避免任何分配并使用我的符号:: get()代替?或者也许有更优雅的解决方案?

编辑:附上一个简单的代码来证明问题。

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;
}

1 个答案:

答案 0 :(得分: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 没有 flyweight

    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 启用了flyweight

    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
    

注意在通过指针序列化时如何跟踪对象。这意味着即使不使用flyweight也没有序列化重复序列,例如, bar对象被使用了3次。

对于foo对象,您可以看到它的实现是&#34;重复数据删除&#34;如果你在使用flyweight时会。

  

Boost Flyweight具有高度可配置性,可以使其性能明显优于默认值。如果您想了解更多信息,请参阅图书馆文档