同步阻塞式程式碼中,執行流程即邏輯流程:
void ReadHttpRequest(HttpRequest& req) {
ReadHeader(req.header);
ReadBody(req.body, req.header);
}
但非同步事件驅動模型下,必須手動管理狀態機:
void OnDataReceived() {
buffer += socket.Read();
switch (state) {
case READ_HEADER: if (ParseHeader()) state = READ_BODY; break;
case READ_BODY: if (ParseBody()) state = DONE; break;
}
}
邏輯被碎片化散落在事件處理器中,狀態變數、緩衝區管理、錯誤處理交織,極難維護。
子流程運行於建立它的執行緒內,開銷比真執行緒小,無同步鎖問題。
class Connection {
SOCKET sock;
std::string buffer;
bool writable = false;
void Start() {
FLOW_START(ProcessLoop()); // 啟動子流程
}
void ProcessLoop() {
while (true) {
HttpRequest req;
try { ReadRequest(req); }
catch (...) { break; }
SendFile(req.uri);
}
sock.Close();
delete this;
}
void ReadRequest(HttpRequest& req) {
ReadHeader(req.header);
ReadBody(req.body, req.header);
}
std::string ReadLine() {
while (true) {
FLOW_WAIT(buffer += ); // 等待資料到達
auto pos = buffer.find('\n');
if (pos != npos) { /* 擷取行 */ return line; }
}
}
void OnRead() { // 主流程事件處理
buffer += sock.Read(sock.Available());
}
void OnWrite() { writable = true; }
};
子流程 ReadLine 在 FLOW_WAIT 處讓出控制權,主流程 OnRead 追加資料後喚醒子流程繼續。邏輯流程保持線性、可讀。
手動管理 scheme/user/host/port/path/query/fragment 狀態,巢狀 if/while 極易出錯。
void AnalyzeUrl() {
START_FLOW { ReadToTail(scheme, "://"); }
START_FLOW { ReadFromHead(host, "/"); }
START_FLOW { ReadFromHead(port, ":"); }
START_FLOW { /* @ 處理 user:pass@host */ }
START_FLOW { ReadFromHead(uri, "/"); }
START_FLOW { ReadFromHead(param, "?"); }
START_FLOW { ReadFromHead(anchor, "#"); }
}
每個 START_FLOW 並行啟動子流程,ReadToTail/ReadFromHead 內部以 FLOW_WAIT 等待游標推進。代碼量大幅減少,新增協定欄位只需加一行 START_FLOW。
編譯器不直接支援 FLOW_START/WAIT,可用輕量級執行緒 + 事件同步模擬:
VFLOW_EVENT)進行等待/喚醒WaitForSingleObject 等待子流程首次 WAITVFLOW_SIGNAL 依序喚醒所有等待者,形成協作式多工關鍵巨集(跨平台 Windows/Linux):
#define VFLOW_START(routine, param) vf_start(routine, param)
#define VFLOW_WAIT(evt) vf_wait(&vf_##evt)
#define VFLOW_SIGNAL(evt) vf_signal(&vf_##evt)
#define VFLOW_TERMINATE(evt) vf_terminate(&vf_##evt)
完整實作見文末 vflow.h/cpp(約 200 行),使用 CreateThread/pthread + 事件/條件變數。
| 維度 | 虛擬流程 | OS 執行緒 |
|---|---|---|
| 記憶體開銷 | 極小(共用堆疊/上下文) | ~1MB 預設堆疊 |
| 切換成本 | 用戶態協作式,無核心切換 | 核心態上下文切換 |
| 同步需求 | 無(單執行緒協作) | 需鎖/原子操作 |
| 阻塞系統呼叫 | 會阻塞整個執行緒 | 獨立阻塞 |
適用場景:非同步 I/O 事件迴圈、協定解析、狀態機密集邏輯。不適用:CPU 密集運算、需真正平行的任務。
START_FLOW { FLOW_WAIT(read_error); /* 錯誤處理 */ }
START_FLOW { FLOW_WAIT(tick - last_recv > TIMEOUT); /* 超時處理 */ }
以獨立虛擬流程處理橫切關注點,主邏輯保持乾淨。
FLOW_START/FLOW_WAIT 兩個原語為核心,可用執行緒+事件高效模擬