基于C++ Coroutines提案 ‘Stackless Resumable Functions’编写的协程库
Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.

test_async_switch_scheduler.cpp 2.9KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. 
  2. #include <chrono>
  3. #include <iostream>
  4. #include <string>
  5. #include <conio.h>
  6. #include <thread>
  7. #include "librf.h"
  8. using namespace resumef;
  9. static scheduler_t* sch_in_main = nullptr;
  10. static std::atomic<scheduler_t*> sch_in_thread = nullptr;
  11. void run_in_thread(channel_t<bool>& c_done)
  12. {
  13. std::cout << "other thread = " << std::this_thread::get_id() << std::endl;
  14. local_scheduler my_scheduler; //产生本线程唯一的调度器
  15. sch_in_thread = this_scheduler(); //本线程唯一的调度器赋值给sch_in_thread,以便于后续测试直接访问此线程的调度器
  16. (void)c_done.write(true); //数据都准备好了,通过channel通知其他协程可以启动后续依赖sch_in_thread变量的协程了
  17. //循环直到sch_in_thread为nullptr
  18. for (;;)
  19. {
  20. auto sch = sch_in_thread.load(std::memory_order_acquire);
  21. if (sch == nullptr)
  22. break;
  23. sch->run_one_batch();
  24. std::this_thread::yield();
  25. }
  26. }
  27. template<class _Ctype>
  28. static void callback_get_long(int64_t val, _Ctype&& cb)
  29. {
  30. using namespace std::chrono;
  31. std::thread([val, cb = std::forward<_Ctype>(cb)]
  32. {
  33. std::this_thread::sleep_for(500ms);
  34. cb(val * val);
  35. }).detach();
  36. }
  37. //这种情况下,没有生成 frame-context,因此,并没有promise_type被内嵌在frame-context里
  38. static future_t<int64_t> async_get_long(int64_t val)
  39. {
  40. awaitable_t<int64_t> awaitable;
  41. callback_get_long(val, [awaitable](int64_t val)
  42. {
  43. awaitable.set_value(val);
  44. });
  45. return awaitable.get_future();
  46. }
  47. //这种情况下,会生成对应的 frame-context,一个promise_type被内嵌在frame-context里
  48. static future_t<> resumable_get_long(int64_t val, channel_t<bool> & c_done)
  49. {
  50. std::cout << "thread = " << std::this_thread::get_id() << ", value = " << val << std::endl;
  51. co_await *sch_in_thread;
  52. val = co_await async_get_long(val);
  53. std::cout << "thread = " << std::this_thread::get_id() << ", value = " << val << std::endl;
  54. co_await *sch_in_main;
  55. val = co_await async_get_long(val);
  56. std::cout << "thread = " << std::this_thread::get_id() << ", value = " << val << std::endl;
  57. co_await *sch_in_thread;
  58. val = co_await async_get_long(val);
  59. std::cout << "thread = " << std::this_thread::get_id() << ", value = " << val << std::endl;
  60. (void)c_done.write(true);
  61. }
  62. void resumable_main_switch_scheduler()
  63. {
  64. sch_in_main = this_scheduler();
  65. channel_t<bool> c_done{ 1 };
  66. std::cout << "main thread = " << std::this_thread::get_id() << std::endl;
  67. std::thread other(&run_in_thread, std::ref(c_done));
  68. GO
  69. {
  70. co_await c_done; //第一次等待,等待run_in_thread准备好了
  71. go resumable_get_long(3, c_done); //开启另外一个协程
  72. //co_await resumable_get_long(3, c_done);
  73. co_await c_done; //等待新的协程运行完毕,从而保证主线程的协程不会提早退出
  74. };
  75. sch_in_main->run_until_notask();
  76. //通知另外一个线程退出
  77. sch_in_thread.store(nullptr, std::memory_order_release);
  78. other.join();
  79. }