Вот детали, которые, на мой взгляд, вы на самом деле ищете, задавая этот вопрос:
SetTimer () сначала просканирует список неядерных таймеров (двусвязный список), чтобы определить, существует ли идентификатор таймера. Если таймер существует, он просто будет сброшен. Если нет, то вызов HMAllocObject происходит и создает пространство для структуры. Структура таймера будет затем заполнена и связана с заголовком списка.
Это будет общая нагрузка на создание каждых 100 ваших таймеров. Это именно то, что делает подпрограмма, за исключением проверки параметров min и max dwElapsed.
Что касается истечения срока действия таймера, список таймеров сканируется с (приблизительно) длительностью наименьшей длительности таймера, наблюдаемой во время последнего сканирования списка таймеров. (На самом деле, на самом деле происходит следующее: таймер ядра устанавливается на длительность наименьшего из найденных пользовательских таймеров, и этот таймер ядра активирует поток, выполняющий проверку истечений таймера пользователя, и вызывает соответствующие потоки, устанавливая флаг в статус их очереди сообщений.)
Для каждого таймера в списке текущая дельта между последним (в мс) списком таймеров и текущим временем (в мс) уменьшается с каждого таймера в списке. Когда он требуется (осталось <= 0), он помечается как «готовый» в своей собственной структуре, и указатель на информацию о потоке считывается из структуры таймера и используется для пробуждения соответствующего потока путем установки флага потока QS_TIMER. Затем он увеличивает счетчик CurrentTimersReady в очереди сообщений. Это все, что делает истечение таймера. Фактические сообщения не опубликованы. </p>
Когда ваш основной обработчик сообщений вызывает GetMessage (), когда другие сообщения недоступны, GetMessage () проверяет наличие QS_TIMER в битах пробуждения вашего потока, а если установлено - генерирует сообщение WM_TIMER, сканирует полный пользовательский таймер list для самого маленького таймера в списке, помеченного как READY и связанного с вашим идентификатором потока. Затем он уменьшает ваш поток CurrentTimersReady count, и если 0, очищает бит пробуждения таймера. Ваш следующий вызов GetMessage () будет вызывать то же самое, пока все таймеры не будут исчерпаны.
Таймеры одного выстрела остаются инстанцированными. Когда они истекают, они помечаются как ожидающие. Следующий вызов SetTimer () с тем же идентификатором таймера просто обновит и повторно активирует оригинал. Оба таймера и один выстрел сбрасываются самостоятельно и умирают только с KillTimer или когда ваш поток или окно разрушены.
Реализация Windows очень проста, и я думаю, что для вас было бы тривиально написать более производительную реализацию.