Большой архив статей, книг, документации по программированию, вебдизайну, компьютерной графике, сетям, операционным системам и многому другому
 
<Добавить в Избранное>    <Сделать стартовой>    <Реклама на сайте>    <Контакты>
  Главная Документация Программы Обои   Экспорт RSS E-Books
 
 

   Программирование -> C/C++ -> Сущность технологии COM


Время жизни сервера

В предыдущих разделах было показано, как СОМ автоматически загружает DLL с целью перенесения реализации объектов в адресное пространство клиентских программ. Однако пока не обсуждалось, как и когда эти DLL выгружаются. Вообще говоря, серверные DLL могут предотвращать преждевременную выгрузку, но именно клиент выбирает момент, когда DLL фактически перестают использоваться. Клиенты, желающие освободить неиспользуемые DLL, вызывают API-функцию СОМ CoFreeUnusedLibraries:

void CoFreeUnusedLibraries(void);

Обычно эта подпрограмма вызывается клиентами в свободное время с целью собрать мусор в своем адресном пространстве. При вызове CoFreeUnusedLibraries СОМ опрашивает каждую из загруженных DLL, чтобы выявить, какие из них не используются. Это делается посредством вызова в каждой DLL функции DllCanUnloadNow, которая должна быть явно экспортирована из этой динамически подключаемой библиотеки.

Функция DllCanUnloadNow, которую экспортирует DLL каждого сервера, должна соответствовать следующей сигнатуре:

HRESULT DllCanUnloadNow(void);

Если DLL желает быть освобожденной, то она возвращает S_OK. Если DLL хочет остаться загруженной, то она возвращает S_FALSE. Серверные DLL должны оставаться загруженными по крайней мере до тех пор, пока сохраняются интерфейсные указатели на ее объекты. Это означает, что в DLL должен быть счетчик всех существующих ссылок на объекты. Чтобы упростить реализацию этого, большинство DLL содержат одну переменную для счетчика блокировок (lock count) и используют две функции для автоматического инкрементирования и декрементирования этого счетчика:

LONG g_cLocks = 0;
void LockModule(void) { InterlockedIncrement(&g_cLocks); } 
void UnlockModule(void) { InterlockedDecrement(&g_cLocks); }

При наличии этих подпрограмм реализация DllCanUnloadNow становится чрезвычайно простой:

STDAPI DllCanUnloadNow(void) 
  { return g_cLocks == 0 ? S_OK : S_FALSE; }

Oстается только вызывать в подходящее время подпрограммы LockModule и UnlockModule.

Существуют две основные причины, которые должны оставлять DLL сервера загруженной: внешние ссылки на экземпляры объектов и объекты класса, а также невыполненные вызовы IClassFactory::LockServer. Вполне очевидно, как добавить поддержку 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 уже не исполняется1. Это означает, что в многопоточных средах выгрузка DLL из своего клиента может осуществляться значительно дольше, чем можно ожидать.


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

Классы и IDL
Эмуляция классов
Категории компонентов
Где мы находимся?

 

 
Интересное в сети
 
10 новых программ
CodeLobster PHP Edition 3.7.2
WinToFlash 0.7.0008
Free Video to Flash Converter 4.7.24
Total Commander v7.55
aTunes 2.0.1
Process Explorer v12.04
Backup42 v3.0
Predator 2.0.1
FastStone Image Viewer 4.1
Process Lasso 3.70.4
FastStone Image Viewer 4.0
Xion Audio Player 1.0.125
Notepad GNU v.2.2.8.7.7
K-Lite Codec Pack 5.3.0 Full


Наши сервисы
Рассылка новостей. Подпишитесь на рассылку сейчас и вы всегда будете в курсе последних событий в мире информационных технологий.
Новостные информеры. Поставьте наши информеры к себе и у вас на сайте появится дополнительный постоянно обновляемый раздел.
Добавление статей. Если вы являетесь автором статьи или обзора на тему ИТ присылайте материал нам, мы с удовольствием опубликуем его у себя на сайте.
Реклама на сайте. Размещая рекламу у нас, вы получите новых посетителей, которые могут стать вашими клиентами.
 
Это интересно
 

Copyright © CompDoc.Ru
При цитировании и перепечатке ссылка на www.compdoc.ru обязательна. Карта сайта.