Singelton lifetime within a dll / bundle
If I create a singleton class in the context of a dll or bundle on mac, the singleton class is instantiated once and used by all instances of the dll. I am using a dll as a plug-in for an application. Now the following thing came to my mind: If I use a singleton Class, it will be shared across multiple instances of the plug-in. However, this makes it difficult to manage the lifetime of the singleton class efficiently. The only way I could think of would be to use a reference count and to make the singleton delete its self when the reference count is 0.
Does anyone have any better ideas on that? Is there any good way to restrict the singleton object to one instance of the dll?
Language is c++, but the solution has to work under windows and mac (being a bundle here). The specification for the dll or bundle are given by the application, so there is noth开发者_JAVA技巧ing to change here.
Here's my golden rule with respect to DLLs and C++.
The code internally to the DLL can be written in C++, but only C functions should get exported from the DLL. But you can have "factory" functions that return back c++ interface pointers
It just gets messy trying to export every method of every class out of a DLL. Thing in terms of components and interfaces.
Since you said DLL, this implies Windows. COM is the answer. COM is your friend. Make a COM DLL and your reference counting problem is mostly solved. Use ATL template libraries (CComObjectRootEx and friends) to make implementation really easy. It gets a little tricky to export a C++ class singleton with COM. Easiest approach is to have a COM class "wrap" the singleton and just forwards all method calls to the real singleton instance.
Now if you are not familiar with the component object model, it can be a little steep in the learning curve. (And most of the reference books spend way too much time on out-of-process COM, proxy/stub DLLs, automation, IDispatch - none of which is relevant to your problem).
Now if you don't have time to learn COM, here's a rough framework on how to implement the DLL singleton pattern without COM.
// singleton.h (consumed by DLL and users of your singleton)
// IMySingleton is an interface class. It only defines pure virtual methods
class IMySingleton
{
public:
virtual int DoSomething()=0;
virtual int DoSomethingElse()=0;
virtual void AddRef()=0;
virtual void Release()=0;
};
// returns back an instance of IMySingleton with the refcount already at "1"
// This function gets exported out of your DLL(either via .def file or __declexport attribute)
HRESULT GetMySingletonInstance(IMySingleton** ppMySingleton);
// -------------------------------------
// singleton.cpp (compiled into your DLL - but is NOT exported out of the DLL)
class CMySingleton : public IMySingleton
{
public:
int m_refcount;
static CMySingleton* s_pInstance;
// returns an adref'd instance of the singleton
static CMySingleton* GetInstance()
{
if (s_pInstance == NULL)
{
s_pInstance = new CMySingleton(); // refcount at 1
}
else
{
s_pInstance->AddRef();
}
return s_pInstance;
}
CMySingleton()
{
m_refcount = 1;
// your initialization code goes here
}
~CMySingleton()
{
// cleanup code
}
int DoSomething()
{
/// your code goes here
return x;
}
int DoSomethingElse()
{
/// your code goes here
return y;
}
void AddRef() {m_refcount++;}
void Release()
{
m_refcount--;
if (m_refcount == 0)
{
s_pInstance = NULL;
delete this;
}
}
};
// exported out of the DLL
HRESULT GetMySingletonInstance(IMySingleton** ppSingleton)
{
*ppSingleton = static_cast<IMySingleton*>(CMySingleton::GetInstance());
}
Callers that need to access the singleton's services need only call GetMySingletonInstance once. When they go away, they just release the singleton instance by calling Release() on the pointer instance they have.
Typically a static object will not be shared across multiple instances of an application or library. Each application has it's own address space and can not access other applications memory. Are you perhaps using shared memory or inter-process communication?
Using a reference count is an excellent idea, there are several so-called "shared-pointer"
libraries available that can help you with implementing it. Here is an implementation I often use: http://www.boost.org/doc/libs/1_45_0/libs/smart_ptr/shared_ptr.htm
精彩评论