studio reales proyectos programacion libro introducción incluye herramientas fundamentos fuente español código con avanzado aplicaciones c++ events visual-c++ com atl

c++ - reales - ¿Cuál es el propósito de las llamadas de Bloqueo()/Desbloqueo() al disparar los eventos COM?



libro de android studio en español pdf (1)

Una pieza típica de eventos de activación de código en un servidor COM ATL es la siguiente (copiada de esta pregunta y recortada un poco):

HRESULT Fire_MessageTrigger() { HRESULT hr = S_OK; T * pThis = static_cast<T *>(this); int count = m_vec.GetSize(); for (int i = 0; i < count; i++) { pThis->Lock(); // I''m asking about this... CComPtr<IUnknown> punkConnection = m_vec.GetAt(i); pThis->Unlock(); // and this IDispatch* pConnection = static_cast<IDispatch *>(punkConnection.p); if (pConnection == 0) continue; DISPPARAMS params = { NULL, NULL, 0, 0 }; hr = pConnection->Invoke(2, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &params, 0, NULL, NULL); } return hr; }

¿Cuál es el propósito de las llamadas Lock() y Unlock() ?


Es una medida de seguridad de subprocesos alrededor de la variable de miembro m_vec (lista de sumideros).

Puede hacer que se ejecute lo siguiente en un hilo concurrente:

template <class T, const IID* piid, class CDV> STDMETHODIMP IConnectionPointImpl<T, piid, CDV>::Advise( _Inout_ IUnknown* pUnkSink, _Out_ DWORD* pdwCookie) { // ... pT->Lock(); *pdwCookie = m_vec.Add(p); // <<--- Modifying m_vec here hRes = (*pdwCookie != NULL) ? S_OK : CONNECT_E_ADVISELIMIT; pT->Unlock();

Su siguiente pregunta sería por qué no están bloqueando unas líneas arriba para acceder a m_vec.GetSize(); .

Esta es la forma en que lo hicieron: están bien si se pierden una entrega de evento individual en caso de acceso vectorial concurrente, siempre y cuando no cree daños en la memoria o comportamiento indefinido. Después de todo, la llamada de suscripción podría suceder un momento después y perderse este evento de todos modos. Lo mismo se aplica al caso de desuscripción de eventos ( Unadvise ).

La prioridad aquí es bloquear lo más raro posible y luego desbloquearlo lo antes posible. Tenga en cuenta que la llamada al receptor se lleva a cabo mientras está desbloqueada, y la lista de receptores puede tomar una modificación mientras iteramos a través de la lista de receptores que realizan llamadas.

UPD. Visual Studio 2008 siempre genera un par de Lock / Unlock . También lo hacen las versiones más nuevas. Del archivo "/ VC / VCWizards / CodeWiz / ATL / ImplementInterface / HTML / 1033 / default.htm":

strProxyMethod += "/t/tfor (int iConnection = 0; iConnection < cConnections; iConnection++)/r/n"+ "/t/t{/r/n"+ "/t/t/tpThis->Lock();/r/n"+ "/t/t/tCComPtr<IUnknown> punkConnection = m_vec.GetAt(iConnection);/r/n"+ "/t/t/tpThis->Unlock();/r/n/r/n";

Las versiones anteriores de VS podían generar código de bloqueo y el código solo se actualiza cuando se vuelve a generar la clase de proxy manualmente desde VS IDE.