Москву завалило снегом в эти выходные. На парковку у работы пришлось заезжать с разбега, т.к. въезд завалили при расчистке дороги. Коллеги как раз тестировали систему видеонаблюдения, результат ниже.
▼
среда, 24 февраля 2010 г.
пятница, 19 февраля 2010 г.
Thread pool sample
Приведу пример кода для RegisterWaitForSingleObject. Для начала создаем событие, по которому задача будет выполнятся. В этом примере это будет Event:
Далее вызываем RegisterWaitForSingleObject:
HANDLE render_event_ = CreateEvent( NULL, FALSE, FALSE, NULL );Создается событие с автопереключением (второй аргумент FALSE), чтобы не вызывать вручную ResetEvent.
Далее вызываем RegisterWaitForSingleObject:
RegisterWaitForSingleObject( &render_wait_obj_, render_event_, RenderCallback, SOME_USER_PARAM, 1000, 0 );Данным вызовом мы говорим вызывать функцию RenderCallback с аргументом SOME_USER_PARAM по событию render_wait_obj_, но не реже одного раза в 1000 миллисекунд. Возвращается render_wait_obj_ типа HANDLE, которое нужно передать в UnregisterWait, когда больше не нужно выполнять задачи зарегестрированного типа (например, при выходе из программы). Функция RenderCallback имеет следующий вид:
VOID CALLBACK RenderCallback( PVOID lpParameter, BOOLEAN TimerOrWaitFired )Когда нужно выполнить задачу RenderCallback просто вызываем SetEvent:
{
// Какие-то действия. Параметр TimerOrWaitFired помогает
// узнать причину вызова RenderCallback.
// Ничего связанного с пулом потоков тут делать не требуется.
}
SetEvent( render_event_ );
среда, 17 февраля 2010 г.
Thread pool
При написании программ приходится сталкиваться с ситуациями, когда хотелось бы сделать какую-либо небольшую задачу асинхронной, но создание потока оказывается слишком накладным. Для этого существует концепция пула потоков (thread pool). Вкратце, суть идеи состоит в том, что существует некоторый набор потоков (пул), который может расширятся при необходимости, либо уменьшаться. Разработчику необходимо указывать функции, которые нужно выполнить асинхронно, а реализация пула потоков сама берется выполнить задачу наиболее эффективно используя возможности многоядерных процессоров. Посмотрим на то, что предлагает Windows API.Простейший сценарий предлагается функцией QueueUserWorkItem. Она принимает указатель на функцию с одним параметром. Указанная задача передается в пул потоков и будет выполнена в соответствии с указанными флагами (флаги помогают пулу потоков определить как лучше выполнить задачу).
Функция RegisterWaitForSingleObject позволяет указать задачу, которая будет выполняться по событию (Event, Mutex, Semaphore, Console input и прочее). Если событие не возникает, то задача выполняется по истечении указанного периода времени. Это, например, удобно использовать для асинхронного отображения видео кадров приходящих по сети. При получении кадра он выводится, а если кадров долго нет, то показывается специальный обновляемый кадр с сообщением о проблеме.
Ещё одна интересная функция — CreateTimerQueueTimer — позволяет создать асинхронный таймер. В этом случае задача ставится в очередь на выполнение регулярно(если другое не задано) через указанный период времени. Уже ясно, что задача выполняется в отдельном потоке, в отличии от обычного таймера Windows.
Интересно отметить, что реализация пула потоков отличается в разных версиях Windows. В Windows XP создается всего 2 потока на 2-х ядерном процессоре, что может оказаться недостаточно для эффективного использования ресурсов. При этом Windows 7, видимо, учитывает не только количество ядер процессора, но и его загрузку в целом. И для той же программы может быть создано более 10 потоков.
вторник, 2 февраля 2010 г.
still here
Блог не забыт, просто много дел и написать не остается времени. Надеюсь, что в конце месяца появится минутка...