вот такая странная задача =) :
имеется ряд (много. сотни, тысячи) событий, которые должны происходить с определенной периодичностью каждое (от десятков миллисекунд до десятков секунд).
как бы по умному организовать работу такого планировщика, чтобы:
1. не было бы постоянной проверки в бесконечном цикле (дабы не грузить процессор)
2. не использовалось бы слишком много потоков
Re: как бы организовать работу планировщика событий
_>вот такая странная задача =) : _>имеется ряд (много. сотни, тысячи) событий, которые должны происходить с определенной периодичностью каждое (от десятков миллисекунд до десятков секунд). _>как бы по умному организовать работу такого планировщика, чтобы: _>1. не было бы постоянной проверки в бесконечном цикле (дабы не грузить процессор) _>2. не использовалось бы слишком много потоков
Насколько я понял, Вы сами хотите генерить эти события.
Тогда на помощь придет виндовый таймер. Можно либо сделать таймер на НОД всех событий,
либо вычислять, когда должно произойти новое событие и переустанавливать таймер.
Если есть опасения, что события в текущем потоке будут обрабатываться слишком долго, в результате
чего следующее событие будет запаздывать, можно делать пост сообщений на другой поток.
Re[2]: как бы организовать работу планировщика событий
Здравствуйте, valery_l, Вы писали:
_>>вот такая странная задача =) : _>>имеется ряд (много. сотни, тысячи) событий, которые должны происходить с определенной периодичностью каждое (от десятков миллисекунд до десятков секунд). _>>как бы по умному организовать работу такого планировщика, чтобы: _>>1. не было бы постоянной проверки в бесконечном цикле (дабы не грузить процессор) _>>2. не использовалось бы слишком много потоков
_>Насколько я понял, Вы сами хотите генерить эти события.
ну да. событие — это что-то, что я должен сделать. периодически. через заданный промежуток времени.
_>Тогда на помощь придет виндовый таймер. Можно либо сделать таймер на НОД всех событий, _>либо вычислять, когда должно произойти новое событие и переустанавливать таймер. _>Если есть опасения, что события в текущем потоке будут обрабатываться слишком долго, в результате _>чего следующее событие будет запаздывать, можно делать пост сообщений на другой поток.
есть момент, про который я явно не сказал — отсутствует виндовое окно =)
Re[3]: как бы организовать работу планировщика событий
N>>>WaitableTimer в отдельном потоке.
_>>а если событий несколько тысяч? (десятков/сотен тысяч)
PD>Что значит несколько сотен тысяч ? В секунду ? В минуту ? Сколько их должно ожидаться в любой момент времени ?
всего несколько десятков/сотен тысяч событий, которые могут возникать с заданной периодичностью.
такое большое количество событий я указал, чтобы подвести к мысли, что WaitForMultipleObjects имеет ограничение на 64 ожидаемых WaitableTimer.
PD>Опиши задачу поподробнее.
модуль (dll/объект/поток[и]), который по расписанию с заданной периодичностью вызывает что-то (типа колбака).
в расписании много событий. периодичность от десятков/сотен миллисекунд, до десятков/сотен секунд.
Re[3]: как бы организовать работу планировщика событий
Здравствуйте, mr_trwister, Вы писали:
_>есть момент, про который я явно не сказал — отсутствует виндовое окно =)
Но ведь ничего не мешает его сделать. На ATL фиктивное окно для таймера делается достаточно просто.
Далее можно использовать такой алгоритм:
1. находим ближайшее событие, устанавливаем таймер на момент, когда это событие (одно или несколько) должно произойти.
2. срабатывает таймер, останавливаем таймер, вызываем нужные колбеки и снова повторяем п.1
Re[7]: как бы организовать работу планировщика событий
Здравствуйте, mr_trwister, Вы писали: _>всего несколько десятков/сотен тысяч событий, которые могут возникать с заданной периодичностью. _>такое большое количество событий я указал, чтобы подвести к мысли, что WaitForMultipleObjects имеет ограничение на 64 ожидаемых WaitableTimer.
Здравствуйте, Alexey Frolov, Вы писали:
AF>Здравствуйте, mr_trwister, Вы писали: _>>всего несколько десятков/сотен тысяч событий, которые могут возникать с заданной периодичностью. _>>такое большое количество событий я указал, чтобы подвести к мысли, что WaitForMultipleObjects имеет ограничение на 64 ожидаемых WaitableTimer.
AF>CreateTimerQueue, CreateTimerQueueTimer вам в помощь
AF>вроде как все условия выполняются, если я конечно внимательно все прочитал
ага. спасибо! надо повнимательнее изучить эту сторону win32api.
как я понимаю, создаем TimerQueue (CreateTimerQueue), а потом в нее добавляем много премного QueueTimer (CreateTimerQueueTimer). правильно?
в дальнейшем очередь сама мониторит эти таймеры и вызывает колбаки, заданные в них независимо от нашего участия?
не очень только понятно в каком потоке вызываются эти колбаки...
Re: как бы организовать работу планировщика событий
Здравствуйте, mr_trwister, Вы писали:
_>имеется ряд (много. сотни, тысячи) событий, которые должны происходить с определенной периодичностью каждое (от десятков миллисекунд до десятков секунд). _>как бы по умному организовать работу такого планировщика, чтобы: _>1. не было бы постоянной проверки в бесконечном цикле (дабы не грузить процессор) _>2. не использовалось бы слишком много потоков
while (живы)
{
выполняем очередное событие (возможно, в отдельном потоке);
вычисляем, сколько времени до следующего события;
ложимся спать (Sleep или WaitForSingleObject(на event выхода, с таймаутом));
}
Re[9]: как бы организовать работу планировщика событий
Здравствуйте, mr_trwister, Вы писали:
_>как я понимаю, создаем TimerQueue (CreateTimerQueue), а потом в нее добавляем много премного QueueTimer (CreateTimerQueueTimer). правильно? _>в дальнейшем очередь сама мониторит эти таймеры и вызывает колбаки, заданные в них независимо от нашего участия?
_>не очень только понятно в каком потоке вызываются эти колбаки...
Да, правильно. Для вызова callback в основном используется механизм APC (asynchronous procedure call), про него почитайте. Но возможны варианты и без него, почитайте в msdn описание последнего параметра (Flags) для CreateTimerQueueTimer, там все варианты расписаны, можете выбрать наиболее удобный и эффективный
Re[2]: как бы организовать работу планировщика событий
_>>имеется ряд (много. сотни, тысячи) событий, которые должны происходить с определенной периодичностью каждое (от десятков миллисекунд до десятков секунд). _>>как бы по умному организовать работу такого планировщика, чтобы: _>>1. не было бы постоянной проверки в бесконечном цикле (дабы не грузить процессор) _>>2. не использовалось бы слишком много потоков
C>
C>while (живы)
C>{
C> выполняем очередное событие (возможно, в отдельном потоке);
C> вычисляем, сколько времени до следующего события;
C> ложимся спать (Sleep или WaitForSingleObject(на event выхода, с таймаутом));
C>}
C>
жуткое дело! если у нас сотни тысяч событий, то мы должны после пробуждения перебирать все и искать то, которое будет ближайшим?
Re[3]: как бы организовать работу планировщика событий
Здравствуйте, mr_trwister, Вы писали:
_>жуткое дело! если у нас сотни тысяч событий, то мы должны после пробуждения перебирать все и искать то, которое будет ближайшим?
А мы их заранее свалим в какую-нибудь структуру, отсортированную по времени ближайшего наступления.
Re[4]: как бы организовать работу планировщика событий
_>>жуткое дело! если у нас сотни тысяч событий, то мы должны после пробуждения перебирать все и искать то, которое будет ближайшим?
C>А мы их заранее свалим в какую-нибудь структуру, отсортированную по времени ближайшего наступления.
а сортировать кто будет?
Re[3]: как бы организовать работу планировщика событий
Здравствуйте, mr_trwister, Вы писали: _>>Тогда на помощь придет виндовый таймер. _>есть момент, про который я явно не сказал — отсутствует виндовое окно =)
Для SetTimer() не обязательно наличае окна.
idEvent
[in] Specifies the timer's identifier.
dwTime
[in] Specifies the number of milliseconds that have elapsed since the system was started. This is the value returned by the GetTickCount function.
Re[4]: как бы организовать работу планировщика событий
_>>>Тогда на помощь придет виндовый таймер. _>>есть момент, про который я явно не сказал — отсутствует виндовое окно =) T>Для SetTimer() не обязательно наличае окна. T>
idEvent
T>[in] Specifies the timer's identifier.
T>dwTime
T>[in] Specifies the number of milliseconds that have elapsed since the system was started. This is the value returned by the GetTickCount function.
хм. интересный подход. единственное, что меня смущает — это "When you specify a TimerProc callback function, the default window procedure calls the callback function when it processes WM_TIMER. Therefore, you need to dispatch messages in the calling thread, even when you use TimerProc instead of processing WM_TIMER."
Re[5]: как бы организовать работу планировщика событий
Здравствуйте, mr_trwister, Вы писали:
_>>>жуткое дело! если у нас сотни тысяч событий, то мы должны после пробуждения перебирать все и искать то, которое будет ближайшим?
C>>А мы их заранее свалим в какую-нибудь структуру, отсортированную по времени ближайшего наступления.
_>а сортировать кто будет?
А будем держать контейнер всегда отсортированным. Если события добавляются редко, будем держать массив, сортировать при старте всей системы. Если часто или если события повторяются каждое через свой интервал — заведём set или ещё какое сбалансированное дерево. Добавление, взятие первого элемента, удаление — O(ln(N)).
Re[7]: как бы организовать работу планировщика событий
Здравствуйте, mr_trwister, Вы писали:
N>>>>WaitableTimer в отдельном потоке.
_>>>а если событий несколько тысяч? (десятков/сотен тысяч)
PD>>Что значит несколько сотен тысяч ? В секунду ? В минуту ? Сколько их должно ожидаться в любой момент времени ?
_>всего несколько десятков/сотен тысяч событий, которые могут возникать с заданной периодичностью.
_>такое большое количество событий я указал, чтобы подвести к мысли, что WaitForMultipleObjects имеет ограничение на 64 ожидаемых WaitableTimer.
Интересно, где вы нашли ограничение 64 объекта обрабатываемых функцией WaitForMultipleObjects. Из своего опыта знаю, что 256 обектов она обрабатываает без проблем