как бы организовать работу планировщика событий
От: mr_trwister  
Дата: 31.03.08 05:58
Оценка:
вот такая странная задача =) :
имеется ряд (много. сотни, тысячи) событий, которые должны происходить с определенной периодичностью каждое (от десятков миллисекунд до десятков секунд).
как бы по умному организовать работу такого планировщика, чтобы:
1. не было бы постоянной проверки в бесконечном цикле (дабы не грузить процессор)
2. не использовалось бы слишком много потоков
Re: как бы организовать работу планировщика событий
От: valery_l Россия  
Дата: 31.03.08 06:51
Оценка:
_>вот такая странная задача =) :
_>имеется ряд (много. сотни, тысячи) событий, которые должны происходить с определенной периодичностью каждое (от десятков миллисекунд до десятков секунд).
_>как бы по умному организовать работу такого планировщика, чтобы:
_>1. не было бы постоянной проверки в бесконечном цикле (дабы не грузить процессор)
_>2. не использовалось бы слишком много потоков

Насколько я понял, Вы сами хотите генерить эти события.
Тогда на помощь придет виндовый таймер. Можно либо сделать таймер на НОД всех событий,
либо вычислять, когда должно произойти новое событие и переустанавливать таймер.
Если есть опасения, что события в текущем потоке будут обрабатываться слишком долго, в результате
чего следующее событие будет запаздывать, можно делать пост сообщений на другой поток.
Re[2]: как бы организовать работу планировщика событий
От: mr_trwister  
Дата: 31.03.08 07:06
Оценка:
Здравствуйте, valery_l, Вы писали:

_>>вот такая странная задача =) :

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

_>Насколько я понял, Вы сами хотите генерить эти события.


ну да. событие — это что-то, что я должен сделать. периодически. через заданный промежуток времени.

_>Тогда на помощь придет виндовый таймер. Можно либо сделать таймер на НОД всех событий,

_>либо вычислять, когда должно произойти новое событие и переустанавливать таймер.
_>Если есть опасения, что события в текущем потоке будут обрабатываться слишком долго, в результате
_>чего следующее событие будет запаздывать, можно делать пост сообщений на другой поток.

есть момент, про который я явно не сказал — отсутствует виндовое окно =)
Re[3]: как бы организовать работу планировщика событий
От: Nuzhny Россия https://github.com/Nuzhny007
Дата: 31.03.08 08:01
Оценка:
Здравствуйте, mr_trwister, Вы писали:

_>есть момент, про который я явно не сказал — отсутствует виндовое окно =)


WaitableTimer в отдельном потоке.
Re[4]: как бы организовать работу планировщика событий
От: mr_trwister  
Дата: 31.03.08 08:14
Оценка:
_>>есть момент, про который я явно не сказал — отсутствует виндовое окно =)

N>WaitableTimer в отдельном потоке.


а если событий несколько тысяч? (десятков/сотен тысяч)
Re[5]: как бы организовать работу планировщика событий
От: Pavel Dvorkin Россия  
Дата: 31.03.08 10:01
Оценка:
Здравствуйте, mr_trwister, Вы писали:

N>>WaitableTimer в отдельном потоке.


_>а если событий несколько тысяч? (десятков/сотен тысяч)


Что значит несколько сотен тысяч ? В секунду ? В минуту ? Сколько их должно ожидаться в любой момент времени ?

Если в секунду — боюсь, что захлебнется вся эта обработка.

Опиши задачу поподробнее.
With best regards
Pavel Dvorkin
Re[6]: как бы организовать работу планировщика событий
От: mr_trwister  
Дата: 31.03.08 10:53
Оценка:
N>>>WaitableTimer в отдельном потоке.

_>>а если событий несколько тысяч? (десятков/сотен тысяч)


PD>Что значит несколько сотен тысяч ? В секунду ? В минуту ? Сколько их должно ожидаться в любой момент времени ?


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

такое большое количество событий я указал, чтобы подвести к мысли, что WaitForMultipleObjects имеет ограничение на 64 ожидаемых WaitableTimer.

PD>Опиши задачу поподробнее.


модуль (dll/объект/поток[и]), который по расписанию с заданной периодичностью вызывает что-то (типа колбака).
в расписании много событий. периодичность от десятков/сотен миллисекунд, до десятков/сотен секунд.
Re[3]: как бы организовать работу планировщика событий
От: valery_l Россия  
Дата: 31.03.08 12:43
Оценка:
Здравствуйте, mr_trwister, Вы писали:

_>есть момент, про который я явно не сказал — отсутствует виндовое окно =)


Но ведь ничего не мешает его сделать. На ATL фиктивное окно для таймера делается достаточно просто.
Далее можно использовать такой алгоритм:
1. находим ближайшее событие, устанавливаем таймер на момент, когда это событие (одно или несколько) должно произойти.
2. срабатывает таймер, останавливаем таймер, вызываем нужные колбеки и снова повторяем п.1
Re[7]: как бы организовать работу планировщика событий
От: Alexey Frolov Беларусь  
Дата: 01.04.08 09:54
Оценка:
Здравствуйте, mr_trwister, Вы писали:
_>всего несколько десятков/сотен тысяч событий, которые могут возникать с заданной периодичностью.
_>такое большое количество событий я указал, чтобы подвести к мысли, что WaitForMultipleObjects имеет ограничение на 64 ожидаемых WaitableTimer.

CreateTimerQueue, CreateTimerQueueTimer вам в помощь

вроде как все условия выполняются, если я конечно внимательно все прочитал
Re[8]: как бы организовать работу планировщика событий
От: mr_trwister  
Дата: 01.04.08 10:31
Оценка:
Здравствуйте, Alexey Frolov, Вы писали:

AF>Здравствуйте, mr_trwister, Вы писали:

_>>всего несколько десятков/сотен тысяч событий, которые могут возникать с заданной периодичностью.
_>>такое большое количество событий я указал, чтобы подвести к мысли, что WaitForMultipleObjects имеет ограничение на 64 ожидаемых WaitableTimer.

AF>CreateTimerQueue, CreateTimerQueueTimer вам в помощь


AF>вроде как все условия выполняются, если я конечно внимательно все прочитал


ага. спасибо! надо повнимательнее изучить эту сторону win32api.

как я понимаю, создаем TimerQueue (CreateTimerQueue), а потом в нее добавляем много премного QueueTimer (CreateTimerQueueTimer). правильно?
в дальнейшем очередь сама мониторит эти таймеры и вызывает колбаки, заданные в них независимо от нашего участия?

не очень только понятно в каком потоке вызываются эти колбаки...
Re: как бы организовать работу планировщика событий
От: Centaur Россия  
Дата: 01.04.08 13:51
Оценка:
Здравствуйте, mr_trwister, Вы писали:

_>имеется ряд (много. сотни, тысячи) событий, которые должны происходить с определенной периодичностью каждое (от десятков миллисекунд до десятков секунд).

_>как бы по умному организовать работу такого планировщика, чтобы:
_>1. не было бы постоянной проверки в бесконечном цикле (дабы не грузить процессор)
_>2. не использовалось бы слишком много потоков

while (живы)
{
    выполняем очередное событие (возможно, в отдельном потоке);
    вычисляем, сколько времени до следующего события;
    ложимся спать (Sleep или WaitForSingleObject(на event выхода, с таймаутом));
}
Re[9]: как бы организовать работу планировщика событий
От: Alexey Frolov Беларусь  
Дата: 01.04.08 17:05
Оценка:
Здравствуйте, mr_trwister, Вы писали:

_>как я понимаю, создаем TimerQueue (CreateTimerQueue), а потом в нее добавляем много премного QueueTimer (CreateTimerQueueTimer). правильно?

_>в дальнейшем очередь сама мониторит эти таймеры и вызывает колбаки, заданные в них независимо от нашего участия?

_>не очень только понятно в каком потоке вызываются эти колбаки...


Да, правильно. Для вызова callback в основном используется механизм APC (asynchronous procedure call), про него почитайте. Но возможны варианты и без него, почитайте в msdn описание последнего параметра (Flags) для CreateTimerQueueTimer, там все варианты расписаны, можете выбрать наиболее удобный и эффективный
Re[2]: как бы организовать работу планировщика событий
От: mr_trwister  
Дата: 02.04.08 06:17
Оценка:
_>>имеется ряд (много. сотни, тысячи) событий, которые должны происходить с определенной периодичностью каждое (от десятков миллисекунд до десятков секунд).
_>>как бы по умному организовать работу такого планировщика, чтобы:
_>>1. не было бы постоянной проверки в бесконечном цикле (дабы не грузить процессор)
_>>2. не использовалось бы слишком много потоков

C>
C>while (живы)
C>{
C>    выполняем очередное событие (возможно, в отдельном потоке);
C>    вычисляем, сколько времени до следующего события;
C>    ложимся спать (Sleep или WaitForSingleObject(на event выхода, с таймаутом));
C>}
C>


жуткое дело! если у нас сотни тысяч событий, то мы должны после пробуждения перебирать все и искать то, которое будет ближайшим?
Re[3]: как бы организовать работу планировщика событий
От: Centaur Россия  
Дата: 02.04.08 14:27
Оценка:
Здравствуйте, mr_trwister, Вы писали:

_>жуткое дело! если у нас сотни тысяч событий, то мы должны после пробуждения перебирать все и искать то, которое будет ближайшим?


А мы их заранее свалим в какую-нибудь структуру, отсортированную по времени ближайшего наступления.
Re[4]: как бы организовать работу планировщика событий
От: mr_trwister  
Дата: 03.04.08 04:33
Оценка:
_>>жуткое дело! если у нас сотни тысяч событий, то мы должны после пробуждения перебирать все и искать то, которое будет ближайшим?

C>А мы их заранее свалим в какую-нибудь структуру, отсортированную по времени ближайшего наступления.


а сортировать кто будет?
Re[3]: как бы организовать работу планировщика событий
От: Tujh Голландия  
Дата: 03.04.08 07:45
Оценка:
Здравствуйте, mr_trwister, Вы писали:
_>>Тогда на помощь придет виндовый таймер.
_>есть момент, про который я явно не сказал — отсутствует виндовое окно =)
Для SetTimer() не обязательно наличае окна.
// timer id
::UINT uiTimerID = 0x0BAD;

// timer procedure
VOID CALLBACK timerProc(::HWND hwnd, ::UINT uMsg, ::UINT_PTR idEvent, ::DWORD dwTime)
{
    /* ToDo: some code 
     * idEvent
     *
     *
     */
};
...
::SetTimer(NULL, uiTimerID, dw_TimerTimeOut, &timerProc);
...
::KillTimer(NULL, uiTimerID);


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]: как бы организовать работу планировщика событий
От: mr_trwister  
Дата: 03.04.08 08:26
Оценка:
_>>>Тогда на помощь придет виндовый таймер.
_>>есть момент, про который я явно не сказал — отсутствует виндовое окно =)
T>Для SetTimer() не обязательно наличае окна.
T>
// timer id
T>::UINT uiTimerID = 0x0BAD;

T>// timer procedure
T>VOID CALLBACK timerProc(::HWND hwnd, ::UINT uMsg, ::UINT_PTR idEvent, ::DWORD dwTime)
T>{
T>    /* ToDo: some code 
T>     * idEvent
T>     *
T>     *
T>     */
T>};
T>...
T>::SetTimer(NULL, uiTimerID, dw_TimerTimeOut, &timerProc);
T>...
T>::KillTimer(NULL, uiTimerID);


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]: как бы организовать работу планировщика событий
От: aloch Россия  
Дата: 03.04.08 14:32
Оценка:
Ну, наверное, сортировка должна выполняться при добавлении нового события.


Re[5]: как бы организовать работу планировщика событий
От: Centaur Россия  
Дата: 03.04.08 16:46
Оценка:
Здравствуйте, mr_trwister, Вы писали:

_>>>жуткое дело! если у нас сотни тысяч событий, то мы должны после пробуждения перебирать все и искать то, которое будет ближайшим?


C>>А мы их заранее свалим в какую-нибудь структуру, отсортированную по времени ближайшего наступления.


_>а сортировать кто будет?


А будем держать контейнер всегда отсортированным. Если события добавляются редко, будем держать массив, сортировать при старте всей системы. Если часто или если события повторяются каждое через свой интервал — заведём set или ещё какое сбалансированное дерево. Добавление, взятие первого элемента, удаление — O(ln(N)).
Re[7]: как бы организовать работу планировщика событий
От: Melamed Россия  
Дата: 03.04.08 17:32
Оценка:
Здравствуйте, mr_trwister, Вы писали:

N>>>>WaitableTimer в отдельном потоке.


_>>>а если событий несколько тысяч? (десятков/сотен тысяч)


PD>>Что значит несколько сотен тысяч ? В секунду ? В минуту ? Сколько их должно ожидаться в любой момент времени ?


_>всего несколько десятков/сотен тысяч событий, которые могут возникать с заданной периодичностью.


_>такое большое количество событий я указал, чтобы подвести к мысли, что WaitForMultipleObjects имеет ограничение на 64 ожидаемых WaitableTimer.


Интересно, где вы нашли ограничение 64 объекта обрабатываемых функцией WaitForMultipleObjects. Из своего опыта знаю, что 256 обектов она обрабатываает без проблем
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.