Windows — COM (C ++) Достаточно ли API блокировки для безопасности потоков в AddRef и Release?

Я знаю, что API-интерфейсы блокировки используются внутри методов AddRef и Release COM-объекта для увеличения / уменьшения потока подсчета ссылок. Но я пытаюсь понять, что здесь достаточно использовать API-интерфейсы блокировки или нам нужны какие-то другие объекты синхронизации, например, Мьютекс. Пока что весь пример кода, который я видел, использовал только API-интерфейсы блокировки.

сценарий— Предположим, я реализовал методы AddRef и Release объекта сообщения следующим образом. Допустим, поток A обращается к объекту сообщения, поэтому счетчик m_lRef равен 1. Как только это сделано с потоком использования объекта сообщения A вызывает метод Release

Метод внутреннего выпуска —
В строке № 9 — m_lRef = 1
В строке № 10 — m_lRef = 0, lRef = 0

Поток A приостанавливается в строке # 10, а другой поток B обращается к тому же сообщению, поэтому он вызывает метод AddRef, который установит значение m_lRef равным 1 в строке # 3. Теперь поток B приостановлен, а поток A возобновляется в строке # 11 — m_lRef = 1, lRef = 0. Поток A удалит объект. Теперь, если поток B пытается получить доступ к тому же объекту; Крах неизбежен.

Мой вопрос — Мой сценарий действителен? если m_lRef = 1, то в идеале никакой другой поток не должен ожидать доступа к объекту. Но чтобы предотвратить сбой в таком неожиданном сценарии, разве мы не должны защищать весь метод выпуска с помощью мьютекса или CS?

1. STDMETHODIMP_(ULONG) CMapiMsg::AddRef()
2. {
3.   LONG lRef = InterlockedIncrement(&m_lRef);
4.   return lRef;
5. }
6.
7. STDMETHODIMP_(ULONG) CMapiMsg::Release()
8. {
9.    LONG lRef = InterlockedDecrement(&m_lRef);
10.   if(0 == lRef)
11.   {
12.    delete this;
13.   }
14.   return lRef;
15. }

Правила подсчета ссылок

5

Решение

Логика идет не так:

m_lRef = 0

Поток A приостанавливается на строке № 10 и другая тема B имеет доступ к тому же сообщению поэтому он вызывает метод AddRef, который установит значение m_lRef равным 1 в строке # 3. Теперь тема B приостановлена, а тема A возобновлена

Если поток B содержит действительную ссылку COM на этот объект, то один поток A не может юридически уменьшить счетчик до нуля. Поток B все еще содержит что-то, поэтому счетчик ссылок должен быть как минимум один, когда поток A освобождает все, что у него есть …

Если поток B только делает свое первое приращение, он должен в любом случае получить указатель на интерфейс откуда-то, что предполагает выдающуюся ссылку. Если что-то передает указатель без строгой ссылки, то это проблема вызывающего абонента, а не проблема подсчета.

В целом, Interlocked API эффективен и достаточен для подсчета ссылок.

7

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]