C ++懒惰单身在加载时挂起

时间:2016-03-11 13:05:12

标签: c++ design-patterns boost

我有懒惰的单件类,需要在第一次调用时使用boost进行序列化。

标题文件:

class Singleton
{
public:

    static Singleton& Instance()
    {
        static Singleton theSingleInstance;
        return theSingleInstance;
    }

    void load();
private:
    Singleton();
    Singleton(const Singleton& root);
    Singleton& operator=(const Singleton&);
    std::map<std::string,std::string > m_desc;

    friend class boost::serialization::access;
    template<typename Archive>
    void serialize(Archive& arc, const unsigned int version)
    {
        arc & BOOST_SERIALIZATION_NVP(m_desc);
    }
    const char* FILENAME = "./config.xml";
};

源文件

#include "singleton.h"
Singleton::Singleton()
{
    load();
}


void Singleton::load()
{
    try
    {
        std::ifstream f(FILENAME);
        boost::archive::xml_iarchive arc(f);
        arc & boost::serialization::make_nvp("Config",Instance());
    }
    catch(...)
    {
        std::cout << "Exception" << std::endl;
    }
}

因此,当我尝试使用此单例启动我的代码时,它会挂起。使用调试器,我可以看到它没有多次进入load()方法(并且没关系)。当我暂停调试器时,它会在return theSingleInstance;行停止,但它也不会多次通过此行的断点。我做错了什么?

3 个答案:

答案 0 :(得分:1)

你可能想要考虑给予单身人士价值语义的做法 - 如果有一天你不想让它成为一个单身人士而且你想避免重构。

另一个优点是它提供了完整的封装:

例如:

$content

答案 1 :(得分:1)

从构造函数中调用load。这意味着,当您...呼叫theSingleInstance时,您在静态Instance的构造函数中

  #0   in Singleton::load at test.cpp <test.cpp>
  #1   in Singleton::Singleton at test.cpp <test.cpp>
  #2   in Singleton::Instance at test.cpp <test.cpp>
  #3   in main at test.cpp <test.cpp>

由于构造c ++ 11函数 - 局部静态保证是线程安全的,这意味着 - 在您的实现中 - 执行将阻塞,直到实例完全构造(或构造失败,因此可以重试)。

当然,这种情况永远不会发生,因为建筑在等待自己。

   0x00000000004030f5 <+629>:   callq  0x402be0 <__cxa_guard_acquire@plt>
=> 0x00000000004030fa <+634>:   test   %eax,%eax
   0x00000000004030fc <+636>:   je     0x402ff1 <Singleton::load()+369>

当然,正如您已经发现的那样,在构建实例时,使用外部访问器 not 可以解决这个问题。

答案 2 :(得分:0)

答案很简单:更换此行

arc & boost::serialization::make_nvp("Config",Instance());

arc & boost::serialization::make_nvp("Config",*this);