PageRenderTime 33ms CodeModel.GetById 19ms RepoModel.GetById 1ms app.codeStats 0ms

/mordor/coroutine.h

http://github.com/mozy/mordor
C Header | 236 lines | 197 code | 38 blank | 1 comment | 6 complexity | 827e99e6a3d61ddadf719fa65060ddec MD5 | raw file
Possible License(s): BSD-3-Clause
  1. #ifndef __MORDOR_COROUTINE_H__
  2. #define __MORDOR_COROUTINE_H__
  3. // Copyright (c) 2009 - Mozy, Inc.
  4. #include <boost/bind.hpp>
  5. #include <boost/function.hpp>
  6. #include <boost/noncopyable.hpp>
  7. #include "exception.h"
  8. #include "fiber.h"
  9. namespace Mordor {
  10. struct DummyVoid;
  11. struct CoroutineAbortedException : virtual OperationAbortedException {};
  12. template <class Result, class Arg = DummyVoid>
  13. class Coroutine : boost::noncopyable
  14. {
  15. public:
  16. Coroutine()
  17. {
  18. m_fiber = Fiber::ptr(new Fiber(boost::bind(&Coroutine::run, this)));
  19. }
  20. Coroutine(boost::function<void (Coroutine &, Arg)> dg)
  21. : m_dg(dg)
  22. {
  23. m_fiber = Fiber::ptr(new Fiber(boost::bind(&Coroutine::run, this)));
  24. }
  25. ~Coroutine()
  26. {
  27. reset();
  28. }
  29. void reset()
  30. {
  31. if (m_fiber->state() == Fiber::HOLD) {
  32. try {
  33. throw boost::enable_current_exception(CoroutineAbortedException());
  34. } catch (...) {
  35. m_fiber->inject(boost::current_exception());
  36. }
  37. }
  38. m_fiber->reset(boost::bind(&Coroutine::run, this));
  39. }
  40. void reset(boost::function<void (Coroutine &, Arg)> dg)
  41. {
  42. reset();
  43. m_dg = dg;
  44. }
  45. Result call(const Arg &arg)
  46. {
  47. m_arg = arg;
  48. m_fiber->call();
  49. return m_result;
  50. }
  51. Arg yield(const Result &result)
  52. {
  53. m_result = result;
  54. Fiber::yield();
  55. return m_arg;
  56. }
  57. Fiber::State state() const
  58. {
  59. return m_fiber->state();
  60. }
  61. private:
  62. void run()
  63. {
  64. try {
  65. m_dg(*this, m_arg);
  66. m_result = Result();
  67. } catch (CoroutineAbortedException &) {
  68. }
  69. }
  70. private:
  71. boost::function<void (Coroutine &, Arg)> m_dg;
  72. Result m_result;
  73. Arg m_arg;
  74. Fiber::ptr m_fiber;
  75. };
  76. template <class Result>
  77. class Coroutine<Result, DummyVoid> : boost::noncopyable
  78. {
  79. public:
  80. Coroutine()
  81. {
  82. m_fiber = Fiber::ptr(new Fiber(boost::bind(&Coroutine::run, this)));
  83. }
  84. Coroutine(boost::function<void (Coroutine &)> dg)
  85. : m_dg(dg)
  86. {
  87. m_fiber = Fiber::ptr(new Fiber(boost::bind(&Coroutine::run, this)));
  88. }
  89. ~Coroutine()
  90. {
  91. reset();
  92. }
  93. void reset()
  94. {
  95. if (m_fiber->state() == Fiber::HOLD) {
  96. try {
  97. throw boost::enable_current_exception(CoroutineAbortedException());
  98. } catch (...) {
  99. m_fiber->inject(boost::current_exception());
  100. }
  101. }
  102. m_fiber->reset(boost::bind(&Coroutine::run, this));
  103. }
  104. void reset(boost::function<void (Coroutine &)> dg)
  105. {
  106. reset();
  107. m_dg = dg;
  108. }
  109. Result call()
  110. {
  111. m_fiber->call();
  112. return m_result;
  113. }
  114. void yield(const Result &result)
  115. {
  116. m_result = result;
  117. Fiber::yield();
  118. }
  119. Fiber::State state() const
  120. {
  121. return m_fiber->state();
  122. }
  123. private:
  124. void run()
  125. {
  126. try {
  127. m_dg(*this);
  128. m_result = Result();
  129. } catch (CoroutineAbortedException &) {
  130. }
  131. }
  132. private:
  133. boost::function<void (Coroutine &)> m_dg;
  134. Result m_result;
  135. Fiber::ptr m_fiber;
  136. };
  137. template <class Arg>
  138. class Coroutine<void, Arg> : boost::noncopyable
  139. {
  140. public:
  141. Coroutine()
  142. {
  143. m_fiber = Fiber::ptr(new Fiber(boost::bind(&Coroutine::run, this)));
  144. }
  145. Coroutine(boost::function<void (Coroutine &, Arg)> dg)
  146. : m_dg(dg)
  147. {
  148. m_fiber = Fiber::ptr(new Fiber(boost::bind(&Coroutine::run, this)));
  149. }
  150. ~Coroutine()
  151. {
  152. reset();
  153. }
  154. void reset()
  155. {
  156. if (m_fiber->state() == Fiber::HOLD) {
  157. try {
  158. throw boost::enable_current_exception(CoroutineAbortedException());
  159. } catch (...) {
  160. m_fiber->inject(boost::current_exception());
  161. }
  162. }
  163. m_fiber->reset(boost::bind(&Coroutine::run, this));
  164. }
  165. void reset(boost::function<void (Coroutine &, Arg)> dg)
  166. {
  167. reset();
  168. m_dg = dg;
  169. }
  170. void call(const Arg &arg)
  171. {
  172. m_arg = arg;
  173. m_fiber->call();
  174. }
  175. Arg yield()
  176. {
  177. Fiber::yield();
  178. return m_arg;
  179. }
  180. Fiber::State state() const
  181. {
  182. return m_fiber->state();
  183. }
  184. private:
  185. void run()
  186. {
  187. try {
  188. m_dg(*this, m_arg);
  189. } catch (CoroutineAbortedException &) {
  190. }
  191. }
  192. private:
  193. boost::function<void (Coroutine &, Arg)> m_dg;
  194. Arg m_arg;
  195. Fiber::ptr m_fiber;
  196. };
  197. }
  198. #endif