Jest to miara bezpieczeństwa gwintów wokół zmiennej składowej m_vec
(lista zlewów).
Można mieć następującą wykonywane na jednoczesnym wątku:
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();
Twoje następne pytanie byłoby, dlaczego nie są one blokowania kilka linijek wyżej wokół dostępu m_vec.GetSize();
.
Oto sposób, w jaki to zrobili: nie są w stanie przegapić pojedynczego zdarzenia w przypadku równoczesnego dostępu do wektorów, o ile nie powoduje to uszkodzenia pamięci lub w inny sposób niezdefiniowanego zachowania. W końcu subskrybowanie połączenia może nastąpić chwilę później i tak czy inaczej przegapi to wydarzenie. To samo dotyczy przypadku anulowania subskrypcji ze zdarzeń (Unadvise
).
Priorytetem jest zablokowanie tak rzadko, jak to możliwe, a następnie odblokowanie tak szybko, jak to możliwe. Zauważ, że wywołanie zlewu następuje podczas odblokowywania, a lista zlewów może zająć modyfikację, podczas gdy my sprawdzamy listę zlewów, które je wywołują.
UPD. Visual Studio 2008 zawsze generuje parę: Lock
/Unlock
. Więc czy nowsze wersje. Od "\ VC \ VCWizards \ CodeWiz \ ATL \ ImplementInterface \ HTML \ 1033 \ default.htm" file:
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";
Wcześniejsze wersje VS można wygenerować kod blokady wolne i kod jest aktualizowany tylko wtedy, gdy ponownie ręcznie generuj klasę proxy z VS IDE.
Okay, widziałem również podobny kod, który nie blokuje() '/' Unlock() '. Czy byłoby słuszne stwierdzenie, że jeśli serwer powinien obsługiwać współbieżność, wówczas cały kod wystrzeliwujący zdarzenia powinien "Zablokować()"/"Odblokować()" bieżący obiekt? – sharptooth
Tu chodzi o bezpieczeństwo nici. Czasami potrzebujesz blokady, czasami nie. Przez cały czas jesteś zainteresowany utrzymaniem stanu zablokowanego w minimalnym możliwym czasie. Zauważ, że z bazą STA ('CComSingleThreadModel') te połączenia powodują opróżnienie metody i wygenerowanie kodu. –
Załóżmy, że mam dziesięć klas COM z tym samym modelem wątkowania innym niż główna STA i każda obsługuje niektóre zdarzenia i wszystkie są implementowane za pomocą 'IConnectionPointImpl'. Czy będę potrzebował takiego blokowania w każdym z nich? – sharptooth