单例的重复实例化

时间:2013-03-04 15:31:17

标签: c++ singleton mex dynamic-library

通过Mex开展一个关于C ++和Matlab合作的大型项目,我们正在与我们的一个单身人士进行斗​​争。

该类是在预处理期间通过宏生成的,所以看起来有点奇怪。

class AdditionalOperation { 
private: 
    const std::string* val; 
    typedef std::map<std::string, const std::string*> StringMap; 

    static StringMap& getStringToPointerMap() 
    { 
        static StringMap map; 
        return map; 
    } 

    static boost::mutex& getMutex()
    { 
        static boost::mutex mutex; 
        return mutex; 
    } 

    AdditionalOperation(const std::string* s)
        :val(s) 
    {} 
private: 
    static std::string* none_string() 
    { 
        static std::string s = "none"; 
        static int count = 0; 
        boost::mutex::scoped_lock lock(getMutex()); 
        if(count++ == 0) { 
            getStringToPointerMap().insert(std::make_pair(s,&s)); 
        } 
        return &s; 
    } 
public: 
    static AdditionalOperation none() 
    { 
        return AdditionalOperation(none_string()); 
    } 

private: 
    static std::string* norm_string() 
    {   
        static std::string s = "norm"; 
        static int count = 0; 
        boost::mutex::scoped_lock lock(getMutex()); 
        if(count++ == 0) { 
            getStringToPointerMap().insert(std::make_pair(s,&s)); 
        } 
        return &s; 
    } 
public: 
    static AdditionalOperation norm() 
    { 
        return AdditionalOperation(norm_string()); 
    } 
private: 
    static void prepare() 
    { 
        none(); 
        norm(); 
    } 
public: 
    static AdditionalOperation fromString(std::string s) 
    { 
        static int count = 0; 
        if(count++ == 0) 
            prepare(); 
        boost::mutex::scoped_lock lock(getMutex()); 
        StringMap& map = getStringToPointerMap(); 
        StringMap::iterator location = map.find(s); 
        if(location == map.end()) { 
            throw UnknownEnumValue(s); 
        } 
        return AdditionalOperation(location->second); 
    } 

    std::string toString() const 
    { 
        return *val; 
    }

    bool operator==(const AdditionalOperation& other) const 
    { 
        return val == other.val; 
    } 

    bool operator!=(const AdditionalOperation& other) const 
    { 
        return !(*this == other); 
    } 
};

所有这些代码都是从这一行生成的(通过如上所述的宏):

DECLARE_SENUM(AdditionalOperation, none, norm);

这是一个很好的界面,我们希望继续使用。

我们希望使用此类作为枚举的替代,因为我们需要将它们从字符串转换为字符串。在这个类中,我们有2个'枚举'成员,即norm和none。

现在我们已经添加了一些日志记录并确定了none_string和norm_string函数内的insert操作被调用了两次,即使我们的计数器应该阻止它。

我们尝试过的一些事情:

  • 我们正在使用动态库,但使用-rdynamic没有帮助。
  • 当我们打印静态变量的地址时,我们可以清楚地看到它们不同。
  • 此类位于动态库中,而动态库又与mex文件链接。这个mex文件正由另一个mex文件通过dlopen动态加载。

我们认为,由于动态库,可能会声明并激活此类的多个实例。但我们也使用其他没有出现任何问题迹象的单身人士。

我希望它足够清楚,可以随时提供额外的信息或澄清!

提前致谢!

1 个答案:

答案 0 :(得分:1)

显然,你的问题太复杂了。

std::string const& to_string(MyEnum e) {
    static std::string const First = "First";
    static std::string const Second = "Second";

    switch(e) {
    case MyEnum::First: return First;
    case MyEnum::Second: return Second;
    }

    throw std::runtime_error("Unknown enum value");
}
如果不是更好更快,

也会起作用。