Language: 한국어 | English
콘솔 예제: 학생(worker) 하나, 스포너(spawner) 둘(교수, 친구), 공유 메일박스 하나. 교수는 과제(assignment)를, 친구는 놀자(play) 메시지를 던지고, 학생은 메일박스를 한 번에 하나씩 비우면서 메시지 종류(kind)에 따라 분기 처리합니다. 네 모듈 모두 같은 Runtime에 붙어 있어, 메일박스는 단일 펌프 스레드에서만 만져지므로 락이 필요 없습니다.
uniflow message_dispatch v1.0.0
professor + friend -> shared mailbox -> student (one Runtime, one pump, lock-free)
----------------------------------------------------------------------
Professor 2/4 sent posted "project" inbox=2
Friend 1/3 sent waiting before next invite
----------------------------------------------------------------------
Mailbox (2 queued)
ASN project need_ability=8 need_time=9h
PLAY soccer 6h
----------------------------------------------------------------------
Student active: ASN lab need_ability=5 need_time=6h
phase: training (+1 ability, 3h)
ability [######..............] 3/10
stress [####................] 2/10
hours spent: 18 messages handled: 3
----------------------------------------------------------------------
Recent activity
student trained -> ability=3 stress=2
professor posted assignment "project" inbox=2
----------------------------------------------------------------------
press Enter to quit
이 예제의 주제는 하나의 협력 펌프 위에서의 메시지 라우팅입니다.
-
메시지 종류별 분기 (dispatch by kind). 학생의
Step1_TakeNext가Message하나를 꺼내Message::Kind로 분기합니다.Assignment는 train/sleep/work 체인으로 가고(Step2_CheckAbility가 능력/스트레스로 다음 step을 가름),Play는 play 체인으로 갑니다. (참고: uf_student.cpp) -
단일 펌프 위의 락 없는 공유 메일박스. 스포너 둘이 push하고 학생이 pop하지만 모든 step이 같은 펌프 스레드에서 돌므로 mailbox.cpp는 뮤텍스 없는 평범한
std::deque입니다. 이것이 uniflow의 핵심 보장입니다: 한 스레드, 협력 모듈 사이에 락 없음. -
SubmitAsync + 폴링으로 블로킹 작업 처리. "n 시뮬레이션 시간" 작업을 인라인 으로 돌리면 펌프가 멈추므로, 각 체인 step은
SubmitAsync(UF_FN(SimHours), ...)로 풀에 떠넘기고, 반환된AsyncId를Next(UF_FN(StepX_Wait), job)으로 대기 step에 넘긴 뒤, 거기서AsyncResult<int>(job)를 폴링합니다 --pending()이면Stay(), 끝나면*r.return_value를 읽습니다. 학생이 "일하는" 동안에도 펌프는 스포너들을 계속 굴립니다. -
콘솔 / ANSI 렌더 패턴.
Flow_Visualization태스크가 매 펌프 라운드마다 세계 상태를g_snap으로 스냅샷하고, 백그라운드 렌더 스레드가 그 스냅샷으로 약 25fps로 대시보드를 그립니다. 메인 스레드는std::getline에서 블로킹 합니다(Enter로 종료). 렌더러가 stdout을 소유하므로 Runtime은SilentObserver로 step 트레이스 출력을 막습니다. console.h / console.cpp 는 simulator 및 city_traffic / pick_and_place 콘솔 렌더러와 동일한 의존성 없는 ANSI 헬퍼입니다.
| 파일 | 역할 |
|---|---|
| uf_student.h / .cpp | worker. Task_Drain 하나가 메시지를 꺼내 종류별로 분기, 체인 실행, SimHours를 SubmitAsync로 떠넘김. |
| uf_professor.h / .cpp | 스포너: 무작위 간격으로 과제 post, 학생을 깨움. |
| uf_friend.h / .cpp | 스포너: 놀자 invite post. 교수와 같은 구조. |
| mailbox.h / .cpp | 공유 inbox (락 없음; 펌프 스레드 전용). |
| globals.h / .cpp | Message 타입, 타이밍 config, 종료 latch, 최근 활동 로그. |
| uf_visualization.h / .cpp | 펌프 측 스냅샷 태스크 + 백그라운드 ANSI 렌더 루프. |
| snapshot.h / .cpp | 펌프 -> 렌더 스레드 전달 (cross-thread라 뮤텍스 사용). |
| console.h / .cpp | 재사용 ANSI 콘솔 헬퍼. |
| app.h | Runtime + 모든 모듈, 2단계 초기화, silent observer, friend 키워드 충돌 회피(friend_). |
| main.cpp | ANSI 활성화, 앱 시작, 렌더 스레드 구동, Enter 블로킹, 종료. |
콘솔 전용, 추가 설치 없음.
Linux / macOS (g++ 또는 clang++):
cd cpp/examples/message_dispatch
g++ -std=c++17 -O2 -I../.. *.cpp -o message_dispatch -pthread
./message_dispatchWindows (MSVC, x64 Native Tools 프롬프트):
cd cpp\examples\message_dispatch
cl /std:c++17 /EHsc /O2 /I..\.. *.cpp /Fe:message_dispatch.exe
message_dispatch.exe참고: 이 데모는 ANSI 터미널을 가정합니다. Windows에서는
console::EnableAnsi()가 콘솔의 VT 처리를 켭니다(Windows Terminal 권장).