Сущность технологии COM



Время жизни сервера - часть 2


Вполне очевидно, как добавить поддержку DllCanUnloadNow в экземпляры и объекты классов. Объекты, расположенные в динамически распределяемой области памяти (такие, как экземпляры классов) просто инкрементируют счетчик блокировок сервера при первом вызове AddRef:

STDMETHODIMP_(ULONG) Chimp::AddRef(void) { if (m_cRef == 0) LockModule(); return InterlockedIncrement(&m_cRef); }

и декрементируют счетчик блокировок при заключительном вызове Release:

STDMETHODIMP_(ULONG) Chimp::Release (void) { LONG res = InterlockedDecrement(&m_cRef); if (res == 0) { delete this; UnlockModule(); } return res; }

Поскольку объекты, не размещенные в динамически распределяемой области памяти (такие, как объекты классов), не содержат счетчика ссылок, при каждом вызове AddRef и Release нужно инкрементировать или декрементировать счетчик блокировок:

STDMETHODIMP_(ULONG) ChimpClass::AddRef(void) { LockModule(); return 2; }

STDMETHODIMP_(ULONG) ChimpClass::Release (void) { UnlockModule(); return 1; }

Объекты классов, которые реализуют IClassFactory, должны устанавливать свои серверные счетчики блокировок на вызовы IClassFactory::LockServer:

STDMETHODIMP ChimpClass::LockServer(BOOL bLock) { if (bLock) LockModule(); else UnlockModule(); return S_OK; }

Как будет обсуждаться в главе 6, IClassFactory::LockServer создана в первую очередь для внепроцессных серверов, но она достаточно проста и для использования во внутрипроцессных серверах.

Следует заметить, что в протоколе CoFreeUnusedLibraries/DllCanUnloadNow неотъемлемо присутствует состояние гонки (race condition). Возможно, что один поток задач будет выполнять заключительное освобождение последнего экземпляра, экспортированного из DLL, в то время как второй поток будет выполнять подпрограмму CoFreeUnusedLibraries. В СОМ приняты все меры предосторожности, чтобы избежать этой ситуации. В частности, в реализацию СОМ под Windows NT 4.0 Service Pack 2 добавлена специальная возможность для борьбы с состоянием гонки. Версия Service Pack 2 библиотеки СОМ определяет, чтобы к DLL обращались из нескольких потоков, и вместо того, чтобы незамедлительно выгружать DLL изнутри CoFreeUnusedLibraries, СОМ ставит DLL в очередь DLL, подлежащих освобождению.Затем СОМ будет ждать неопределенное время, пока не разрешит этим неиспользуемым серверным DLL освободиться посредством последующего вызова CoFreeUnusedLibraries, подтверждающего, что никаких остаточных вызовов Release уже не исполняется. Это означает, что в многопоточных средах выгрузка DLL из своего клиента может осуществляться значительно дольше, чем можно ожидать.

1

Вероятно, в Windows NT 5.0 будет предусмотрена дополнительная поддержка для подтверждения того, что DLL освобождаются быстро и безошибочно. Подробности можно найти в документации SDK.




Содержание  Назад  Вперед