По сути, мое приложение использует Windows очереди таймеров для создания таймера, который будет вызываться каждые 50 миллисекунд с использованием CreateTimerQueueTimer
(ссылка ниже).
Вот краткий обзор функции, которая будет вызываться при вызове таймера:
// Set up the timer
CreateTimerQueueTimer(timerHandle, NULL, foo, NULL, 20, 20, WT_EXECUTEDEFAULT);
//…
//...
// Timer callback
void foo(void* param, BOOLEAN b)
{
static bool doing_timer_func = false;
if (!doing_timer_func)
{
doing_timer_func = true;
MyType *p = reinterpret_cast<MyType*>(param);
CallSomeFunction(); // This function may take more than 50 ms.
}
doing_timer_func = false;
}
Я утверждаю, что следующий код (даже если он запускается как однопоточное приложение) небезопасен с точки зрения гарантии того, что doing_timer_func
логическое значение всегда предотвращает проблемы повторного входа. Несмотря на то, что bool
, кажется, "делает работу", в целом код выглядит безопасным, но так ли это?
Флаг WM_EXECUTEDEFAULT
, согласно документации Windows, поместит таймер в рабочий поток, не связанный с вводом-выводом, поэтому, по сути, приложение использует несколько потоков, даже если приложение предназначено для быть однопоточным.
Поскольку таймеры, используемые здесь, являются объектами синхронизации, у меня всегда было представление, что для защиты от чего-либо неожиданного приложение должно использовать надлежащие примитивы синхронизации (мьютекс, критическая секция, SRWLocks и т. д.) 1027 *.), А не просто логическая переменная (и).
Я здесь не прав, а код действительно безопасный?
Дополнительная информация:
Используется компилятор - Visual Studio 2010.