A.- Быстрый ответ
Предполагается, что у вас есть объект Mutex
и Lock
(ваш пробег может отличаться):
#define MY_OWN_LOCK(mm_mutex) \
\
if(bool b_1227F2B8_136B_11E1_973D_7D0B4924019B = false) \
; \
else \
for(Lock lock_1227F2B8_136B_11E1_973D_7D0B4924019B(mm_mutex); \
!b_1227F2B8_136B_11E1_973D_7D0B4924019B; \
b_1227F2B8_136B_11E1_973D_7D0B4924019B = true)
, который можно использовать как:
Mutex mutex ;
void foo()
{
// not locked
MY_OWN_LOCK(mutex)
{
// locked
}
// not locked
}
B.- Подробный ответ
Это зависит от библиотеки, которую вы будете использовать.
B.1 - Предварительные условия
Предположим, у вас есть:
- a
Mutex
объект, который имеет lock()
и unlock()
методы - a
Lock
объект, который имеет конструктор с Mutex
в качестве параметра и вызывает его lock()
метод при строительстве и unlock()
метод при разрушении
Итак, у вас есть что-то вроде:
class Mutex
{
public :
lock() ;
unlock() ;
// etc.
} ;
class Lock
{
Mutex & m_mutex ;
public :
Lock(Mutex & p_mutex) : m_mutex(p_mutex)
{ this->m_mutex.lock() ; }
~Lock()
{ this->m_mutex.unlock() ; }
// etc.
} ;
B.2 - Raw C + использование
Если вы не знакомы с RAII C ++, ваш код будет выглядеть следующим образом:
void foo()
{
// not locked
mutex.lock() ;
// locked !
mutex.unlock() ;
// not locked
}
Этот код настолько неправильный, что я никогда не буду его обсуждать (Google "исключительная безопасность", если необходимо).
B.3 - использование необработанного C ++
void foo()
{
// not locked
{
Lock lock(mutex) ;
// locked !
}
// not locked
}
B.4 - использование макросов с расширенным C ++
со следующим макросом:
#define LOCK(mm_mutex) \
\
if(bool b = false) \
; \
else \
for(Lock lock(mm_mutex); !b; b = true)
Вы будетев состоянии написать:
void foo()
{
// not locked
LOCK(mutex)
{
// locked !
}
// not locked
}
B.5 - Почему это так сложно?
Большинство макросов блокировки полагаются на объект блокировки для проверки.Для этого требуется либо реализация Safe Bool Idiom (что является избыточным для текущего использования), либо необходимость в объекте блокировки, который можно привести к bool
, что приводит к его собственному (большому) наборунедостатки в классе.
В текущей реализации if
используется для объявления логического значения, которое будет контролировать выполнение тела for
, тогда как сам for
используется для объявления Lock
сам объект.
Я полагаю, что этот шаблон называется чем-то вроде "инъекции переменной C ++".
B.6 - Производительность?
Обратите внимание, что вы что-то блокируетепоэтому код внутри mutex.lock()
и mutex.unlock()
будет занимать намного больше циклов, чем что-либо в макросе.
В неоптимизированных сборках будут отображаться переходы if
и for
(например,попробуйте пошагово на визуальном отладчике), но в оптимизированной сборке все if
и for
будут оптимизированы (нет разницы между сборкой, сгенерированной "использованием необработанного C ++" и макросом "использование C ++ ".
B.7 - Осторожно !!!
Макрос выше упрощен для образовательных целей.Чтобы использовать его в рабочем коде, вы должны:
- «пространство имен» имени макроса (то есть префикс его с каким-то уникальным именем, как
BOOST_
часть макроса BOOST_FOREACH
) - делает логическую
b
и переменную Lock lock
уникальными, чтобы они не конфликтовали с кодом пользователя.Я обычно использую для этого суффикс GUID / UUID (например, b_ABCD_ABCD_AB_ABCDEF
и lock_ABCD_ABCD_AB_ABCDEF
)
B.8 - Источники
Я впервые увидел этот шаблон в статье (яверю Андрею Александреску), и действительно, я искал его, когда наткнулся на этот ТАК вопрос.
: -)
Как только я найду источник, я обновлю этоответ с правильной ссылкой.
Редактировать: Найдено источник !!!