Время жизни статических данных в COM-объектах
От: frogkiller Россия  
Дата: 04.09.06 10:56
Оценка:
Наверное, сюда более правильно, чем в "COM/DCOM/ActiveX"...

Можно ли как-то управлять временем жизни статических данных, объявленных в COM-библиотеке?
Например, если какой-то класс внутри COM-объекта (сорри за терминологию, не знаю как сказать правильнее)
использует Meyers singleton.

template <class T>
class CMeyersSingleton
{
protected:
    CMeyersSingleton() {}
    ~CMeyersSingleton() {}
public:
    static T &GetInstance()
    {
        static T obj;
        return obj;
    }
};

class CTestClass1 : public CMeyersSingleton<CTestClass1>
{
    friend class CMeyersSingleton<CTestClass1>;
private:
    CTestClass1()
    {
        printf("CTestClass1()\r\n");
    }
public:
    int Perform() { return 0; }
    ~CTestClass1()
    {
        printf("~CTestClass1()\r\n");
    }
};

class ATL_NO_VTABLE CTest : 
    public CComObjectRootEx<CComSingleThreadModel>,
    public CComCoClass<CTest, &CLSID_Test>,
    public IDispatchImpl<ITest, &IID_ITest, &LIBID_COMWithStaticSingletonLib, /*wMajor =*/ 1, /*wMinor =*/ 0>
{
public:
    CTest()
    {
        printf("CTest()\r\n");
    }
    virtual ~CTest()
    {
        printf("~CTest()\r\n");
    }

    STDMETHOD(Perform)(void);

        ...
}

STDMETHODIMP CTest::Perform(void)
{
    int qwe = CTestClass1::GetInstance().Perform();
    return S_OK;
}


При первом обращении к CTest::Perform() создаётся экземпляр CTestClass1. А вот когда он уничтожится?

#import "..\COMWithStaticSingleton\Debug\comwithstaticsingleton.dll"

void Test()
{
    COMWithStaticSingletonLib::ITestPtr ptr;
    ptr.CreateInstance(__uuidof(COMWithStaticSingletonLib::Test));
    ptr->Perform();
    //ptr.Release();
}

int _tmain(int argc, _TCHAR* argv[])
{
    CoInitialize(NULL);
    printf("CoInitialize(NULL)\r\n");
    Test();
    printf("Test() finished\r\n");
    CoUninitialize();
    printf("CoUninitialize()\r\n");
    return 0;
}


Результат:

CoInitialize(NULL)
CTest()
CTestClass1()
~CTest()
Test() finished
~CTestClass1()
CoUninitialize()


Получается, что CreateInstance() сам как-то вызывает LoadLibrary(), причём нельзя явно это задать и получить хэндл на библиотеку. А затем нельзя явно её выгрузить через FreeLibrary(). В результате статические объекты уничтожаются только при CoUninitialize(), а не когда счётчик ссылок на объект будет равен нулю. В принципе это логично, но не всегда удобно. Может, можно в этот механизм как-то залезть руками? (Понимаю, что этот пример притянут за уши, и можно выполнять нужные действия в деструкторе ~CTest(), но интересует сама возможность влиять на подобные side-effect'ы)
Курица — это инструмент, с помощью которого одно яйцо производит другие.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.