基于C++ Coroutines提案 ‘Stackless Resumable Functions’编写的协程库
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

test_async_modern_cb.cpp 4.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. //依赖 https://github.com/tearshark/modern_cb.git 项目
  2. //依赖 https://github.com/tearshark/librf.git 项目
  3. #include <future>
  4. #include <string>
  5. #include <iostream>
  6. #include "modern_callback.h"
  7. //原旨主义的异步函数,其回调写法大致如下
  8. template<typename _Input_t, typename _Callable_t>
  9. void tostring_async_originalism(_Input_t&& value, _Callable_t&& token)
  10. {
  11. std::thread([callback = std::move(token), value = std::forward<_Input_t>(value)]
  12. {
  13. callback(std::to_string(value));
  14. }).detach();
  15. }
  16. //使用原旨主义的方式扩展异步方法来支持future
  17. template<typename _Input_t>
  18. auto tostring_async_originalism_future(_Input_t&& value)
  19. {
  20. std::promise<std::string> _promise;
  21. std::future<std::string> _future = _promise.get_future();
  22. std::thread([_promise = std::move(_promise), value = std::forward<_Input_t>(value)]() mutable
  23. {
  24. _promise.set_value(std::to_string(value));
  25. }).detach();
  26. return std::move(_future);
  27. }
  28. //----------------------------------------------------------------------------------------------------------------------
  29. //下面演示如何扩展tostring_async函数,以支持future模式
  30. template<typename _Input_t, typename _Callable_t>
  31. auto tostring_async(_Input_t&& value, _Callable_t&& token)
  32. {
  33. MODERN_CALLBACK_TRAITS(token, void(std::string));
  34. std::thread([callback = MODERN_CALLBACK_CALL(), value = std::forward<_Input_t>(value)]
  35. {
  36. callback(std::to_string(value));
  37. }).detach();
  38. MODERN_CALLBACK_RETURN();
  39. }
  40. //演示异步库有多个异步回调函数,只要按照Modern Callback范式去做回调,就不再需要写额外的代码,就可以适配到future+librf,以及更多的其他库
  41. template<typename _Ty1, typename _Ty2, typename _Callable_t>
  42. auto add_async(_Ty1&& val1, _Ty2&& val2, _Callable_t&& token)
  43. {
  44. MODERN_CALLBACK_TRAITS(token, void(decltype(val1 + val2)));
  45. std::thread([=, callback = MODERN_CALLBACK_CALL()]
  46. {
  47. using namespace std::literals;
  48. std::this_thread::sleep_for(0.1s);
  49. callback(val1 + val2);
  50. }).detach();
  51. MODERN_CALLBACK_RETURN();
  52. }
  53. //演示异步库有多个异步回调函数,只要按照Modern Callback范式去做回调,就不再需要写额外的代码,就可以适配到future+librf,以及更多的其他库
  54. template<typename _Ty1, typename _Ty2, typename _Callable_t>
  55. auto muldiv_async(_Ty1&& val1, _Ty2&& val2, _Callable_t&& token)
  56. {
  57. MODERN_CALLBACK_TRAITS(token, void(std::exception_ptr, decltype(val1 * val2), decltype(val1 / val2)));
  58. std::thread([=, callback = MODERN_CALLBACK_CALL()]
  59. {
  60. using namespace std::literals;
  61. std::this_thread::sleep_for(0.1s);
  62. auto v1 = val1 * val2;
  63. if (val2 == 0)
  64. callback(std::make_exception_ptr(std::logic_error("divided by zero")), v1, 0);
  65. else
  66. callback(nullptr, v1, val1 / val2);
  67. }).detach();
  68. MODERN_CALLBACK_RETURN();
  69. }
  70. #include "use_future.h"
  71. static void example_future()
  72. {
  73. using namespace std::literals;
  74. //使用lambda作为异步回调函数,传统用法
  75. tostring_async_originalism(-1.0, [](std::string&& value)
  76. {
  77. std::cout << value << std::endl;
  78. });
  79. std::this_thread::sleep_for(0.5s);
  80. tostring_async(1.0, [](std::string&& value)
  81. {
  82. std::cout << value << std::endl;
  83. });
  84. std::this_thread::sleep_for(0.5s);
  85. std::cout << "......" << std::endl;
  86. //支持future的用法
  87. std::future<std::string> f1 = tostring_async_originalism_future(5);
  88. std::cout << f1.get() << std::endl;
  89. std::future<std::string> f2 = tostring_async(6.0f, std_future);
  90. std::cout << f2.get() << std::endl;
  91. }
  92. #include "librf.h"
  93. #include "use_librf.h"
  94. static void example_librf()
  95. {
  96. //支持librf的用法
  97. GO
  98. {
  99. #ifndef __clang__
  100. try
  101. #endif
  102. {
  103. int val = co_await add_async(1, 2, use_librf);
  104. std::cout << val << std::endl;
  105. //muldiv_async函数可能会抛异常,取决于val是否是0
  106. //异常将会带回到本协程里的代码,所以需要try-catch
  107. auto [a, b] = co_await muldiv_async(9, val, use_librf);
  108. std::string result = co_await tostring_async(a + b, use_librf);
  109. std::cout << result << std::endl;
  110. }
  111. #ifndef __clang__
  112. catch (const std::exception & e)
  113. {
  114. std::cout << "exception signal : " << e.what() << std::endl;
  115. }
  116. catch (...)
  117. {
  118. std::cout << "exception signal : who knows?" << std::endl;
  119. }
  120. #endif
  121. };
  122. resumef::this_scheduler()->run_until_notask();
  123. }
  124. void resumable_main_modern_cb()
  125. {
  126. example_future();
  127. example_librf();
  128. }