Я хочу реализовать класс планировщика, который любой объект может использовать для планирования тайм-аутов и отмены при необходимости.По истечении времени ожидания эта информация будет отправлена установщику / владельцу времени ожидания в это время асинхронно.
Итак, для этой цели у меня есть 2 основных класса WindowsTimeout и WindowsScheduler.
class WindowsTimeout
{
bool mCancelled;
int mTimerID; // Windows handle to identify the actual timer set.
ITimeoutReceiver* mSetter;
int cancel()
{
mCancelled = true;
if ( timeKillEvent(mTimerID) == SUCCESS) // Line under question # 1
{
delete this; // Timeout instance is self-destroyed.
return 0; // ok. OS Timer resource given back.
}
return 1; // fail. OS Timer resource not given back.
}
WindowsTimeout(ITimeoutReceiver* setter, int timerID)
{
mSetter = setter;
mTimerID = timerID;
}
};
class WindowsScheduler
{
static void CALLBACK timerFunction(UINT uID,UINT uMsg,DWORD dwUser,DWORD dw1,DWORD dw2)
{
WindowsTimeout* timeout = (WindowsTimeout*) uMsg;
if (timeout->mCancelled)
delete timeout;
else
timeout->mDestination->GEN(evTimeout(timeout));
}
WindowsTimeout* schedule(ITimeoutReceiver* setter, TimeUnit t)
{
int timerID = timeSetEvent(...);
if (timerID == SUCCESS)
{
return WindowsTimeout(setter, timerID);
}
return 0;
}
};
Мои вопросы:
Q.1.Когда выполняется вызов WindowsScheduler :: timerFunction (), в каком контексте этот вызов выполняется?Это просто функция обратного вызова, и я думаю, что она выполняется контекстом ОС, верно?Если это так, препятствует ли этот вызов другим задачам, которые уже выполняются?Я имею в виду, что обратные вызовы имеют более высокий приоритет, чем любая другая пользовательская задача?
Q.2.Когда установщик тайм-аута хочет отменить свой тайм-аут, он вызывает WindowsTimeout :: cancel ().Тем не менее, всегда существует вероятность того, что статический вызов timerFunction будет отозван операционной системой, упреждая операцию отмены, например, сразу после оператора mCancelled = true.В таком случае экземпляр тайм-аута будет удален функцией обратного вызова.Когда функция pre-empted cancel () приходит снова, после того, как функция обратного вызова завершает выполнение, она попытается получить доступ к атрибуту удаленного экземпляра (mTimerID), как вы можете видеть в строке: «Строка под вопросом № 1» вкод.
Как избежать такого случая?
Обратите внимание, что этот вопрос является улучшенной версией предыдущих версий, одной из моих собственных: Таймер мультимедиа Windows с аргументом обратного вызова