Question

Working on a large project concerning C++ and Matlab cooperation through Mex we are currently struggling with one of our singletons.

The class is being generated through macros during preprocessing so it may seem a bit odd.

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

All this code is generated from this line (through macros as stated above):

DECLARE_SENUM(AdditionalOperation, none, norm);

Which is a nice interface that we'd like to keep on using.

We want to use this class as a replacement for enumerations because we need to translate them from string and to a string. In this class we have 2 'enumeration' members namely norm and none.

Now we have added some logging and have determined that the insert operation inside the none_string and norm_string function is being called twice even though our counter should prevent this.

Some things we have tried :

  • We are working with a dynamic library but using -rdynamic did not help.
  • When we print the address of the static variables we can clearly see that they differ.
  • This class is situated within a dynamic library which in turn is linked with a mex file. This mex file is being dynamically loaded by another mex file through dlopen.

We were thinking that perhaps multiple instances of this class are declared and active because of the dynamic library. But we also use other kind of singletons that have not shown any sign of problems.

I hope it was clear enough, additional information or clarification can always be provided!

Thanks in advance!

Was it helpful?

Solution

You are, clearly, overcomplicating the problem.

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

would work as well, if not better and faster.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top