На web страницах вешали таймеры. Их запускал браузер.
1. денди-
* основной поток. Ждет в безконечном цикле пока не изменится ячейка памяти.
Что случилось? Логика игры и запись через порты IO (2004..2007) в видеопроцесор.
Звук. ... Ждем дальше .
* (немаскируемое) прерывание, пусть раз в 1/25 секунды. Из него опрашивают джойстик.
пишется в ячейку памяти.
2. windows- CreateWindow(...) // создаем окно. Оно вешает в безконечный цикл (или ждуший) свои области экрана и функции.
while ( GetMessage( MSG)!=WM_QUIT ){ MSG -> WinProc(); }
DestroyWindow();
Функция GetMessage помешается в массив в ОС, и если с ее окном что то происходит она возврашает управление (пробуждает поток). Потоки если ждут как правило усыпляются - экономия ЦПУ.
WinProc(MSG){// это тело вызывается когда чтото присылается окну.
switch( MSG.code){ //что за сообшение
case КНОПКА_НАЖАТА:
....
switch ( key){//какая кнопка нажата?
case LEFT: g_siPosX++; g_nScreenChanged=1; break; //вправо, и перерисовать экран.
}
break;
case таймер: if (g_nScreenChanged) SendMessage(..., WM_PAINT); break; //анимация не спит.
case WM_PAINT: Рисую окно. break; //рисовать все и сбросить флаг что надо перерисовать
}
3. Игра -
Используются функции ожидания - WaitForSingleObject и Semaphiore&Events или условные переменные.
* поток для ввода пользователя - ждать события DirectInput или ReadPort :).
WaitForIOEvent(code); <i> или любая друга ждушая функция. Хоть прерывание. Часто с таймером чтоб не висеть. </i>
switch(code){
case МОНИТОР_ВКЛЮЧОН: SendEvent(GRAPHICS_PAINT_ALL); ...
}
* поток логики игры -
Событие что чтото изменилось или таймер.
Двигает все- физика и анимация.
Вводим корректировку на ввод пользователя, меняя скорости, направления,...
Ставим по ходу дела флаги.
Применяем флаги заставляя рисовать области или весь экран. Посылаем сообшения, семафорим или через условные переменные.
* поток для окна - Ждет события для рисования, размеров окна, ... (опенгло не даст рисовать из другово потока чем создавало окно. DirectX использует указатели а не номера потоков тот дает. )
lock_...(условная_переменная, мютекс).
while (ЧтоСлучилось==0){
r=wait...( условная_переменная,мютекс).
if (r==TIME_OUT){ if (*pQuit) break; }
}
unlock(...);
switch( ЧтоСлучилось ){
case ОБНОВИТЬ СЦЕНУ: //событие надо обновить сцену.
РИСУЕМ_В_БУФФЕР. //может тоже быть отдельным потоком, чтоб окно быстро риагировало на события.
// тогда запускаем рендеринг и ждем событие что готово.
PushPin(SCREEN_RESET,1); //прерывание - сброс экрана.
PushPin(SCREEN_RESET,0);
SendBufferToSPI(НАШ БУФФЕР);
break;
}
Если вы пишете для Windows то это тоже как набор скриптов, событиям WM_MOUSEMOVE, WM_PAINT, WM_CLOSE, WM_CHAR, ... они будут вызываться системой. Можно сделать таймер. Если чего то ждете - запускаете свой дополнительный поток, посылая сообщения куда то еше.
Если пишите для arduino - тогда да, надо цикл. Хотя и там можно ждать например таймер или прерывание ( как MS-DOS программы).
Когда ваш PHP что то записывает в файл он копирует память, то есть ждет. Ждет пока другой поток запишет на диск. Ждет опять пока винт не скажет что все хорошо. Тогда берет следующую команду. Поэтому коректнее сказать что скриптовые и не скриптовые это уровень абстракции. Например g-basic преобразовывал
10 PRINT 2+2
в [000][010][130 например][2][+][2][END]
а при исполнении выполнял как ваш PHP. Это компилирующий интерпретатор был.