C++非同步回調如何更優雅?

最近一直在做伺服器開放,遇到過但多進程單線程結構,但進程內多線程還是時常會有,比如邏輯線程與DB線程之間的交互,邏輯線程向DB線程查詢數據的過程:一般是 邏輯線程調用DB線程的介面,並傳入回調函數,同時還有狀態數據,查詢回調回來被再次投遞到邏輯線程,拿到查詢結果和狀態數據繼續處理。一個邏輯很可能處理一堆回調,不勝其煩,有什麼好的辦法使得整個過程更簡單或者更優雅? PS:協程貌似夠優雅了


如果僅僅如題主所說:C++ 11 中的 async + lambda (std::async - cppreference.com)就能滿足你的要求,主流編譯器都支持

性能方面,沒具體測試過,不過VS下面,async是基於Parallel Patterns Library (PPL)的,作為一個並行處理庫,線程切換的開銷,應該是很低的

其實這種跳來跳去的函數模型,代碼可讀性很糟糕,邏輯混亂,使用任務堆棧的方式更好,並且代碼實現起來邏輯模塊分離也更直觀,擴展性也好,附加的諸如系統資源分配,功能模塊監測等實現起來也更簡單


如果你用的是VC++2013,就可以有個__await關鍵字(將來會進入C++17),寫起來就跟C#的await一摸一樣,別提多開心了,非同步再也沒有什麼回調了。


樓主需要promise,不是c++標準的那個難用的要死的promise,

必須是javascript形式的promise才好用。

在這裡給樓主寫了一個,以追求方便使用和高效能為目標

GitHub - xhawk18/promise-cpp: Promise API implemented by cpp as Javascript promise style.

這個庫的特點:

1. 使用友好。完全header only的,只有一個頭文件,promise.hpp;使用時也不需要用戶有各種奇怪的尖括弧&<&>。

2. 可完全類比js的promise --

用 newPromise代替js的 new Promise

用 lambda函數代替js的內嵌函數

用 d.resolve 代替 js的resolve

用 d.reject 代替js的reject

3. resolve和reject可不帶參數,或帶一個任意類型的參數。帶參數時,下一級then/fail的參數類型一定要匹配,否則運行出錯。

4. 支持then, fail, always三個級聯調用。

5. 支持用fail函數捕捉異常。

限制:

暫不支持多線程(非同步promise下,多線程似乎沒太必要)

對比下,該c++庫的實現(使用libuv執行非同步loop循環) --

Defer newDelay(uint64_t timeout) {
return newPromise([timeout](Defer d) {
setTimeout([d]() {
d-&>resolve();
}, timeout);
});
}

int main() {
uv_loop_t *loop = uv_default_loop();

newPromise([](Defer d) {
setTimeout([d]() {
printf("In timerout 1
");
d.resolve(893);
}, 1000);
}).then([](const int vv) {
printf("In then 1, vv = %d
", vv);
return newDelay(1000);
}).then([]() {
printf("In then 2
");
return newDelay(2000);
}).then([]() {
printf("In then 3
");
return newDelay(3000);
}).then([]() {
printf("In last then
");
});

return uv_run(loop, UV_RUN_DEFAULT);
}

javascript的實現 --

function newDelay(timeout) {
return new Promise(function(resolve, reject) {
setTimeout(function() {
resolve();
}, timeout);
});
}

(function main() {
new Promise(function(resolve, reject) {
setTimeout(function() {
console.log("In timerout 1");
resolve(893);
}, 1000);
}).then(function(vv) {
console.log("In then 1, vv = " + vv);
return newDelay(1000);
}).then(function() {
console.log("In then 2");
return newDelay(2000);
}).then(function() {
console.log("In then 3");
return newDelay(3000);
}).then(function() {
console.log("In last then");
});
})();


要優雅那就用協程吧,看上去就像同步方式一樣簡單,並且切換開銷小,性能要更高一些!

非同步回調呢,第一就是太重,上下文切換有點多,qps高的時候cpu很容易就壓爆了;第二就是不夠優雅,一個完整的邏輯硬生生的被分割成好多段,定義一堆callback,一堆on_call函數,寫著不舒服,看起來也不好懂,不符合人的直覺!


公司環境C99,本著不想寫太多callback,想上網抄一波代碼,哦不借鑒一下的想法,然並卵。


擼一個非同步工作流吧!表面上還是和正常同步邏輯一樣寫,但是實質上是非同步過程,只是非同步過程對於使用的人來說是透明的。


推薦閱讀:

[C++] 能否設計一個一般的計時函數?
unity項目越大編譯速度越慢 ue4用藍圖秒編譯 背後分別的原因是什麼?
c++的強制類型轉換?
對於 計算機圖形/界面/可視化/遊戲畫面/遊戲引擎 的疑惑?
VS編寫C++程序,如何在一個工程裡面創建多個包含main函數的文件?

TAG:C | 多線程 | 遊戲編程 |