Как синхронизировать доступ к глобальной переменной с очень частыми чтениями / очень редкими записями?

Я работаю над инфраструктурой отладочного протоколирования для серверного приложения. Каждая точка логирования в исходном коде определяет свой уровень (CRITICAL, ERROR и т.д.) среди других параметров. Поэтому в исходном коде точка логирования выглядит так:

DBG_LOG_HIGH( … )

что является макросом, который расширяется до

if ( CURRENT_DEBUG_LOG_LEVEL >= DEBUG_LOG_LEVEL_HIGH ) {
   // prepare and emit log record
}

где DEBUG_LOG_LEVEL_HIGH - предопределенная константа (допустим, 2), а CURRENT_DEBUG_LOG_LEVEL - некоторое выражение, которое оценивается как текущий уровень логирования отладки, установленный пользователем. Простейшим подходом будет определение CURRENT_DEBUG_LOG_LEVEL следующим образом:

extern int g_current_debug_log_level;
#define CURRENT_DEBUG_LOG_LEVEL (g_current_debug_log_level)

Я хотел бы позволить пользователю изменять текущий уровень отладочной регистрации во время выполнения приложения, и это нормально, если изменение займет несколько секунд. Приложение многопоточное, и изменения g_current_debug_log_level могут быть легко сериализованы (например, с помощью CRITICAL_SECTION), но чтобы не повлиять на производительность, выражение ( CURRENT_DEBUG_LOG_LEVEL >= DEBUG_LOG_LEVEL_HIGH ) должно выполняться как можно быстрее, поэтому я хотел бы избежать использования механизма синхронизации потоков.

Итак, мои вопросы:

  1. Может ли отсутствие синхронизации при чтении g_current_debug_log_level привести к считыванию некорректного значения? Хотя это не должно влиять на корректность работы приложения, поскольку пользователь мог установить текущий уровень отладочного журнала в неверное значение, это может повлиять на производительность приложения, поскольку это может привести к тому, что оно будет выдавать очень большой объем отладочного журнала в течение неконтролируемого периода времени.

  2. Будет ли мое решение гарантировать, что изменение текущего уровня регистрации отладки достигнет всех потоков через приемлемое время (допустим, несколько секунд)? В идеале я бы хотел, чтобы операция изменения уровня была синхронной, чтобы пользователь, получив подтверждение об изменении уровня, мог рассчитывать на то, что последующий лог будет выдан в соответствии с новым уровнем.

Я также буду очень признателен за любые предложения по альтернативным реализациям, удовлетворяющим вышеуказанным требованиям (минимальное влияние на производительность при сравнении уровней и синхронное изменение уровня с задержкой не более нескольких секунд).

9
задан Sergey Kleyman 30 September 2011 в 11:50
поделиться