Для предотвращения взаимоблокировки все типы апартаментов СОМ поддерживают реентерабельность (повторную входимость). Когда поток в апартаменте делает запрос на объект вне апартамента вызывающего объекта посредством заместителя, то могут обслуживаться и другие поступающие запросы методов, пока поток вызывающего объекта находится в ожидании ORPC-ответа па первый запрос. Без этой поддержки было бы невозможно создавать системы, основанные на совместно работающих объектах. При написании следующего кода предполагалось, что CLSID_Callback является внутрипроцессным сервером, поддерживающим модель вызывающего потока, и что CLSID_Object является классом, сконфигурированным для активации на удаленной машине:
ICallback *pcb = 0; HRESULT hr = CoCreateInstance(CLSID_Callback, 0, CLSCTX_ALL, IID_ICallback, (void**)&pcb); assert(SUCCEEDED(hr)); // callback object lives in this apt. // объект обратного вызова живет в этом апартаменте I0bject "po = 0; hr = CoCreateInstance(CLSID_Object, 0, CLSCTX_REMOTE_SERVER, IID_Iobject, (void **)&po); assert(SUCCEEDED(hr)); // object lives in different apt. // объект живет в другом апартаменте // make a call to remote object, marshaling a reference to // the callback object as an [in] parameter // делаем вызов удаленного объекта, маршалируя ссылку // на объект обратного вызова как на [in]-параметр hr = po->UseCallback(pcb); // clean up resources // очищаем ресурсы pcb->Release(); pco->Release();
На рис. 5.6 показано, что если апартамент вызывающего объекта не поддерживает реентерабельность, то следующая реализация метода UseCallback вызовет взаимоблокировку: