0

Mex を介した C++ と Matlab の連携に関する大規模なプロジェクトに取り組んでおり、現在、シングルトンの 1 つに苦労しています。

クラスは前処理中にマクロを介して生成されているため、少し奇妙に見えるかもしれません。

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

使い続けたい素敵なインターフェースです。

列挙型を文字列から文字列に変換する必要があるため、このクラスを列挙型の代わりとして使用したいと考えています。このクラスには、norm と none という 2 つの「列挙型」メンバーがあります。

ここでログを追加し、none_string および norm_string 関数内の挿入操作が 2 回呼び出されていることを確認しましたが、カウンターはこれを防ぐ必要があります。

私たちが試したいくつかのこと:

  • 動的ライブラリを使用していますが、-rdynamic を使用しても効果がありませんでした。
  • 静的変数のアドレスを出力すると、それらが異なることがはっきりとわかります。
  • このクラスは動的ライブラリ内に配置されており、動的ライブラリは mex ファイルにリンクされています。この mex ファイルは、dlopen を介して別の mex ファイルによって動的にロードされています。

動的ライブラリが原因で、このクラスの複数のインスタンスが宣言され、アクティブになっている可能性があると考えていました。しかし、問題の兆候が見られない他の種類のシングルトンも使用しています。

十分に明確であったことを願っています。追加情報や説明はいつでも提供できます。

前もって感謝します!

4

1 に答える 1