coroutine.hpp 2.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. #ifndef __COROUTINE_HPP__
  2. #define __COROUTINE_HPP__
  3. #include <vector>
  4. #include "corotypes.hpp"
  5. #include "mpcio.hpp"
  6. // The top-level coroutine runner will call run_coroutines with
  7. // a MPCTIO, and we should call its send() method. Subcoroutines that
  8. // launch their own coroutines (and coroutine running) will call
  9. // run_coroutines with a yield_t instead, which we should just call, in
  10. // order to yield to the next higher level of coroutine runner.
  11. static inline void send_or_yield(MPCTIO &tio) { tio.send(); }
  12. static inline void send_or_yield(yield_t &yield) { yield(); }
  13. // Use this version if you have a variable number of coroutines (or a
  14. // larger constant number than is supported below).
  15. template <typename T>
  16. inline void run_coroutines(T &mpctio_or_yield, std::vector<coro_t> &coroutines) {
  17. // Loop until all the coroutines are finished
  18. bool finished = false;
  19. while(!finished) {
  20. // If this current function is not itself a coroutine (i.e.,
  21. // this is the top-level function that launches all the
  22. // coroutines), here's where to call send(). Otherwise, call
  23. // yield() here to let other coroutines at this level run.
  24. send_or_yield(mpctio_or_yield);
  25. finished = true;
  26. for (auto &c : coroutines) {
  27. // This tests if coroutine c still has work to do (is not
  28. // finished)
  29. if (c) {
  30. finished = false;
  31. // Resume coroutine c from the point it yield()ed
  32. c();
  33. }
  34. }
  35. }
  36. }
  37. // Use one of these versions if you have a small fixed number of
  38. // coroutines. You can of course also use the above, but the API for
  39. // this version is simpler.
  40. template <typename T>
  41. inline void run_coroutines(T &mpctio_or_yield, const coro_lambda_t &l1)
  42. {
  43. std::vector<coro_t> coroutines;
  44. coroutines.emplace_back(l1);
  45. run_coroutines(mpctio_or_yield, coroutines);
  46. }
  47. template <typename T>
  48. inline void run_coroutines(T &mpctio_or_yield, const coro_lambda_t &l1,
  49. const coro_lambda_t &l2)
  50. {
  51. std::vector<coro_t> coroutines;
  52. coroutines.emplace_back(l1);
  53. coroutines.emplace_back(l2);
  54. run_coroutines(mpctio_or_yield, coroutines);
  55. }
  56. template <typename T>
  57. inline void run_coroutines(T &mpctio_or_yield, const coro_lambda_t &l1,
  58. const coro_lambda_t &l2, const coro_lambda_t &l3)
  59. {
  60. std::vector<coro_t> coroutines;
  61. coroutines.emplace_back(l1);
  62. coroutines.emplace_back(l2);
  63. coroutines.emplace_back(l3);
  64. run_coroutines(mpctio_or_yield, coroutines);
  65. }
  66. template <typename T>
  67. inline void run_coroutines(T &mpctio_or_yield, const coro_lambda_t &l1,
  68. const coro_lambda_t &l2, const coro_lambda_t &l3,
  69. const coro_lambda_t &l4)
  70. {
  71. std::vector<coro_t> coroutines;
  72. coroutines.emplace_back(l1);
  73. coroutines.emplace_back(l2);
  74. coroutines.emplace_back(l3);
  75. coroutines.emplace_back(l4);
  76. run_coroutines(mpctio_or_yield, coroutines);
  77. }
  78. #endif