How to use Singletons over dll boundaries?

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • Hellhound
    New Member
    • Sep 2010
    • 1

    How to use Singletons over dll boundaries?

    Hi all,

    actually i migrate our Linux sources to windows using MSYS/MinGW. Now I've to migrate several global utility singletons (template based) , which are placed in a shared library, everything is working fine with Linux and in context of the dll.

    The singleton:
    Code:
    template <class T>
    
    class brSingleton
    {
    public:
        static T& getInstance(){
            if(m_instance == 0)
                m_instance = new T;
    
            return *m_instance;
        }
    
        virtual void delInstance(){
            delete(m_instance);
            m_instance = 0;
        }
    
    protected:
        brSingleton() {}
        virtual ~brSingleton()  {}
    
    private:
        brSingleton(const brSingleton& s) {}
        const brSingleton& operator=(const brSingleton& s) const {}
        brSingleton& operator=(const brSingleton& s) {}
    
        static T*	m_instance;
    };
    
    template <class T>
    T* brSingleton<T>::m_instance = 0;
    But I'm getting errors when I try to use it from several different dll's, while got different singleton instances in those dll's. I tried to use the windows dllimport/export macros but i fail.

    The import/export macros in brCommons.h
    Code:
    #ifdef WIN32
      #ifdef MYLIB_EXPORTS
        #define MYLIB_API __declspec(dllexport)
      #else
        #define MYLIB_API __declspec(dllimport)
      #endif
    #else
      //define empty values for linux OS
      #define MYLIB_API
    #endif
    The concrete singleton header:
    Code:
    class MYLIB_API brConfiguration : public brCore::brSingleton<brConfiguration>
    {
        friend class brCore::brSingleton<brConfiguration>;
    
    public:
        enum Types {
            INT,    // 0
            LONG,   // 1
            UINT,   // 2
            ULONG,  // 3
            FLOAT,  // 4
            DOUBLE, // 5
            STRING, // 6
            CHAR,   // 7
            ANY     // 8
        };
    
        struct valuetype{
            brAnyType value;
            Types type;
        };
    
       void setValue(std::string key, const int& value);
       void setValue(std::string key, const long& value);
       void setValue(std::string key, const unsigned int& value);
       void setValue(std::string key, const unsigned long& value);
       void setValue(std::string key, const float& value);
       void setValue(std::string key, const double& value);
       void setValue(std::string key, const std::string& value);
       void setValue(std::string key, const char* value);
       void setAnyValue(std::string key, brAnyType value);
    
       // handling lex_t uses.
       brAnyType getValue(std::string key, brAnyType default_value = 0);
      
       valuetype getInternalValue(std::string key);
    
    protected:
       brConfiguration();
       virtual ~brConfiguration();
       void setValue(std::string key, brAnyType value, Types type);
    
    private:
       typedef std::map<std::string,valuetype> MapT;
       MapT m_configs;
    };
    And the concrete singleton cpp module header to force an dll export and template export:

    Code:
    // Ensure that the dll hader will be exported
    #define MYLIB_EXPORTS
    #include <brConfig/brConfiguration.h>
    
    // You must also export the template instantiation Singleton< MyClass > into 
    // the DLL you are compiling. That should be it!
    template MYLIB_API class binrev::brCore::brSingleton<brConfiguration>;
    Knows anyone a solution?
    I'm thankfully for any hint or point in the right direction.

    Best regards,
    Chris

    P.S.: You could get the complete test source here: http://sourceforge.net/projects/binr...st.7z/download

    I've included two executables in the lib subfolder demonstrating the problem. The ConfigTest.exe shows that the singleton works fine in dll context, the SingletonTest.e xe demonstrating the problem using te singleton across differend dll's.
  • weaknessforcats
    Recognized Expert Expert
    • Mar 2007
    • 9214

    #2
    It does not appear that the singleton is set up correctly.

    Using multiple dlls should njot be a problem. Using multiple threads will be an issue since the code is not thread safe.

    The singleton needs a global point of acess and there needs to be exactly one singleton instance for the entire progem regardless of the number of dlls.

    I also believe there is a design weakness due to the use of friend classes. A friend class breaks encapsulation and that's a no-no.

    Read this: http://bytes.com/topic/c/insights/65...erns-singleton

    Comment

    Working...