как предотвратить взаимоблокировку при использовании wxCRIT_SECT_LOCKER

Я пишу синглтон-класс Logger в C ++. Этот класс предоставляет API-протоколирование для нескольких потоков. чтобы сделать это потокобезопасным, я использую wxCRIT_SECT_LOCKER макро.

скажем, у меня есть в моем классе Logger следующие функции (простой пример):

void Logger::error( string msg )
{
wxCRIT_SECT_LOCKER(adapter_locker, gs_LogBufferShield);

// do something such as getting/setting class members
m_err_cnt++;

do_log("Error: " + msg);
}

void Logger::warning( string msg )
{
wxCRIT_SECT_LOCKER(adapter_locker, gs_LogBufferShield);

// do something such as getting/setting class members
m_warn_cnt++;

do_log("Warning: " + msg);
}

void Logger::do_log( string msg )
{
wxCRIT_SECT_LOCKER(adapter_locker, gs_LogBufferShield);

// do something such as getting/setting class members
m_log_cnt++;cout << msg << endl;
}

Проблема:

когда Logger :: предупреждение () называется мы войдем в критическую секцию дважды, один раз в Logger :: предупреждение () и еще раз в * Logger :: do_log () *.

Если вы согласны с тем, что проблема реальна и может вызвать взаимоблокировку, как я могу избежать множественных блокировок (используя класс / макрос wxCriticalSection).

1

Решение

Часто это делается для создания внутренних API-интерфейсов, которые не принимают блокировки, которые вызываются общедоступными API-интерфейсами, которые принимают блокировки.

void Logger::error( string msg )
{
wxCRIT_SECT_LOCKER(adapter_locker, gs_LogBufferShield);
m_err_cnt++;
do_log_internal("Error: " + msg);
}

void Logger::warning( string msg )
{
wxCRIT_SECT_LOCKER(adapter_locker, gs_LogBufferShield);
m_warn_cnt++;
do_log_internal("Warning: " + msg);
}

void Logger::do_log( string msg )
{
wxCRIT_SECT_LOCKER(adapter_locker, gs_LogBufferShield);
do_log_internal(msg);
}

void Logger::do_log_internal( string msg )
{
m_log_cnt++;
cout << msg << endl;
}

Тем не менее, для вашей проблемы, вы можете использовать wxMutex напрямую, и используйте тип wxMUTEX_RECURSIVE когда вы его построите. Таким образом, мьютекс имеет счет. Когда мьютекс впервые блокируется, счетчик устанавливается на 1. Если тот же поток снова захватывает мьютекс, он увеличивает счет. Освобождение мьютекса уменьшает счет. Когда счет достигает 0, мьютекс разблокируется.

1

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

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

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector