feat: 게임 엔진 생명주기 및 스케줄링 관련 클래스 추가

This commit is contained in:
2025-12-28 11:09:18 +00:00
parent 50ef39be4e
commit d13898e486
6 changed files with 409 additions and 1 deletions
@@ -0,0 +1,62 @@
import type { TurnDaemonCommand, TurnDaemonControlQueue } from './types.js';
type Waiter = {
deadlineMs: number | null;
resolve: (command: TurnDaemonCommand | null) => void;
timeoutId?: ReturnType<typeof setTimeout>;
};
export class InMemoryControlQueue implements TurnDaemonControlQueue {
// 단일 프로세스 내에서 쓰는 간단한 제어 큐.
private queue: TurnDaemonCommand[] = [];
private waiters: Waiter[] = [];
enqueue(command: TurnDaemonCommand): void {
const waiter = this.waiters.shift();
if (waiter) {
if (waiter.timeoutId) {
clearTimeout(waiter.timeoutId);
}
waiter.resolve(command);
return;
}
this.queue.push(command);
}
async drain(): Promise<TurnDaemonCommand[]> {
if (this.queue.length === 0) {
return [];
}
const drained = this.queue.slice();
this.queue.length = 0;
return drained;
}
async waitUntil(deadlineMs: number | null): Promise<TurnDaemonCommand | null> {
if (this.queue.length > 0) {
return this.queue.shift() ?? null;
}
return new Promise((resolve) => {
const waiter: Waiter = { deadlineMs, resolve };
if (deadlineMs !== null) {
const delay = Math.max(0, deadlineMs - Date.now());
waiter.timeoutId = setTimeout(() => {
this.removeWaiter(waiter);
resolve(null);
}, delay);
}
this.waiters.push(waiter);
});
}
getDepth(): number {
return this.queue.length;
}
private removeWaiter(waiter: Waiter): void {
const index = this.waiters.indexOf(waiter);
if (index >= 0) {
this.waiters.splice(index, 1);
}
}
}