코루틴 (Coroutines)
코루틴은 실행 중 특정 지점에서 중지(yield)하고, 나중에 중지된 지점부터 다시 실행할 수 있는 함수입니다. Zephyr에서 비동기 상태 머신, AI 로직 및 순차적 애니메이션을 관리하는 핵심 메커니즘입니다.
선언 및 생성
코루틴은 coroutine fn 키워드를 사용하여 선언합니다. 코루틴 함수를 호출하면 본문이 즉시 실행되는 대신, 함수의 중단된 상태를 나타내는 코루틴 객체가 반환됩니다.
coroutine fn task() -> void {
print("1단계");
yield;
print("2단계");
}
let c = task(); // 함수가 생성되었으나 아직 실행되지는 않음재개와 중지
실행은 resume 연산자가 코루틴 객체에 적용될 때만 시작되거나 계속됩니다.
resume c; // "1단계"를 출력하고 yield에서 중지
resume c; // "2단계"를 출력하고 리턴값 반환 (Yield values)
yield 구문은 선택적으로 표현식을 포함할 수 있습니다. 이 값은 resume 연산의 결과로 호출자에게 반환됩니다.
coroutine fn counter(n: int) -> int {
let mut i = 0;
while i < n {
yield i;
i += 1;
}
}
let c = counter(3);
print(resume c); // 0
print(resume c); // 1
print(resume c); // 2코루틴 상태 조회
모든 코루틴 인스턴스(CoroutineFrame)는 내장 속성을 제공합니다.
.done: 함수가 완전히 반환(return)되어 종료되었는지 확인하는 bool 값입니다..suspended: 현재 코루틴이 진행 중이 아니라yield상태로 대기 중인지 확인하는 bool 값입니다.
중첩 호출 및 Yield 전파 (Deep Yielding)
Zephyr는 딥 일딩(Deep yielding)을 지원합니다. 코루틴에서 일반 함수(fn)를 호출하고, 그 함수(또는 콜 스택 더 아래의 함수)에서 yield를 실행하면 전체 호출 체인이 중지됩니다. 코루틴 객체는 재개될 때까지 이 깊은 콜 스택 상태를 유지합니다.
fn helper() -> void {
print("헬퍼 내부");
yield;
}
coroutine fn main_task() -> void {
helper();
print("메인으로 복귀");
}구현 구조 (Architecture)
모든 코루틴은 힙(Heap)에 상주합니다. 각 인스턴스는 다음과 같은 정보를 포함하는 CoroutineFrame에 의해 지원됩니다:
- 모든 레지스터(0-255)의 스냅샷
- 현재 피연산자 스택(Operand stack)
- 명령어 포인터(PC)
- 소속된 클로저의 업밸류(Upvalues) 포인터
OS 쓰레드 방식과 달리 콜스택의 포인터를 보존하기 위한 불필요한 메모리 낭비가 전혀 없습니다. 코루틴이 중지될 때 프레임은 메모리 오버헤드를 줄이기 위해 선택적으로 압축됩니다. 다시 재개될 때 VM은 레지스터 뱅크를 복원하고 저장된 명령어 포인터부터 실행을 이어갑니다. 확장을 통해, C++ 호스트 틱(Tick) 단위에서 관리 중인 모든 스크립트 객체들의 진행 여부를 유연하게 파악할 수 있도록 진화하고 있습니다.