dll / bundle中的Singleton生命周期

时间:2011-02-20 23:22:26

标签: c++ singleton object-lifetime

如果我在mac上的dll或bundle的上下文中创建单例类,则单例类将被实例化一次并被dll的所有实例使用。我使用dll作为应用程序的插件。现在我想到了以下事情:如果我使用单例类,它将在插件的多个实例之间共享。然而,这使得难以有效地管理单例类的寿命。我能想到的唯一方法是使用引用计数,并在引用计数为0时使单例删除它自己。

有没有人对此有任何更好的想法?有没有什么好方法可以将singleton对象限制为dll的一个实例?

语言是c ++,但解决方案必须在windows和mac下工作(在这里是一个包)。应用程序给出了dll或bundle的规范,因此这里没有任何改变。

2 个答案:

答案 0 :(得分:1)

这是关于DLL和C ++的黄金法则。

DLL内部的代码可以用C ++编写,但只有C函数才能从DLL中导出。但是你可以使用“工厂”函数返回c ++接口指针

尝试从DLL中导出每个类的每个方法都变得很乱。就组件和接口而言。

既然你说过DLL,这意味着Windows。 COM就是答案。 COM是你的朋友。创建一个COM DLL,你的引用计数问题基本上解决了。使用ATL模板库(CComObjectRootEx和朋友)使实现变得非常简单。使用COM导出C ++类单例有点棘手。最简单的方法是让COM类“包装”单例并将所有方法调用转发给真正的单例实例。

现在,如果您不熟悉组件对象模型,那么学习曲线可能会有点陡峭。 (并且大多数参考书花费了太多时间在进程外COM,代理/存根DLL,自动化,IDispatch - 这些都与您的问题无关)。

现在,如果你没有时间学习COM,这里有一个关于如何在没有COM的情况下实现DLL单例模式的粗略框架。

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

需要访问单例服务的调用者只需调用一次GetMySingletonInstance。当它们消失时,它们只是通过在它们具有的指针实例上调用Release()来释放单例实例。

答案 1 :(得分:0)

通常,不会在应用程序或库的多个实例之间共享静态对象。每个应用程序都有自己的地址空间,无法访问其他应用程序内存。您是使用共享内存还是进程间通信?

使用引用计数是一个很好的主意,有几个所谓的"shared-pointer"库可以帮助您实现它。以下是我经常使用的实现:http://www.boost.org/doc/libs/1_45_0/libs/smart_ptr/shared_ptr.htm