fiber.hpp 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  1. // Copyright Oliver Kowalke 2013.
  2. // Distributed under the Boost Software License, Version 1.0.
  3. // (See accompanying file LICENSE_1_0.txt or copy at
  4. // http://www.boost.org/LICENSE_1_0.txt)
  5. #ifndef BOOST_FIBERS_FIBER_H
  6. #define BOOST_FIBERS_FIBER_H
  7. #include <algorithm>
  8. #include <exception>
  9. #include <memory>
  10. #include <utility>
  11. #include <boost/assert.hpp>
  12. #include <boost/config.hpp>
  13. #include <boost/intrusive_ptr.hpp>
  14. #include <boost/predef.h>
  15. #include <boost/fiber/detail/config.hpp>
  16. #include <boost/fiber/detail/disable_overload.hpp>
  17. #include <boost/fiber/context.hpp>
  18. #include <boost/fiber/fixedsize_stack.hpp>
  19. #include <boost/fiber/policy.hpp>
  20. #include <boost/fiber/properties.hpp>
  21. #include <boost/fiber/segmented_stack.hpp>
  22. #ifdef BOOST_HAS_ABI_HEADERS
  23. # include BOOST_ABI_PREFIX
  24. #endif
  25. #ifdef _MSC_VER
  26. # pragma warning(push)
  27. # pragma warning(disable:4251)
  28. #endif
  29. namespace boost {
  30. namespace fibers {
  31. class BOOST_FIBERS_DECL fiber {
  32. private:
  33. friend class context;
  34. using ptr_t = intrusive_ptr<context>;
  35. ptr_t impl_{};
  36. void start_() noexcept;
  37. public:
  38. using id = context::id;
  39. fiber() = default;
  40. template< typename Fn,
  41. typename ... Arg,
  42. typename = detail::disable_overload< fiber, Fn >,
  43. typename = detail::disable_overload< launch, Fn >,
  44. typename = detail::disable_overload< std::allocator_arg_t, Fn >
  45. >
  46. #if BOOST_COMP_GNUC < 50000000
  47. explicit fiber( Fn && fn, Arg && ... arg) :
  48. #else
  49. fiber( Fn && fn, Arg ... arg) :
  50. #endif
  51. fiber{ launch::post,
  52. std::allocator_arg, default_stack(),
  53. std::forward< Fn >( fn), std::forward< Arg >( arg) ... } {
  54. }
  55. template< typename Fn,
  56. typename ... Arg,
  57. typename = detail::disable_overload< fiber, Fn >
  58. >
  59. #if BOOST_COMP_GNUC < 50000000
  60. fiber( launch policy, Fn && fn, Arg && ... arg) :
  61. #else
  62. fiber( launch policy, Fn && fn, Arg ... arg) :
  63. #endif
  64. fiber{ policy,
  65. std::allocator_arg, default_stack(),
  66. std::forward< Fn >( fn), std::forward< Arg >( arg) ... } {
  67. }
  68. template< typename StackAllocator,
  69. typename Fn,
  70. typename ... Arg
  71. >
  72. #if BOOST_COMP_GNUC < 50000000
  73. fiber( std::allocator_arg_t, StackAllocator && salloc, Fn && fn, Arg && ... arg) :
  74. #else
  75. fiber( std::allocator_arg_t, StackAllocator && salloc, Fn && fn, Arg ... arg) :
  76. #endif
  77. fiber{ launch::post,
  78. std::allocator_arg, std::forward< StackAllocator >( salloc),
  79. std::forward< Fn >( fn), std::forward< Arg >( arg) ... } {
  80. }
  81. template< typename StackAllocator,
  82. typename Fn,
  83. typename ... Arg
  84. >
  85. #if BOOST_COMP_GNUC < 50000000
  86. fiber( launch policy, std::allocator_arg_t, StackAllocator && salloc, Fn && fn, Arg && ... arg) :
  87. #else
  88. fiber( launch policy, std::allocator_arg_t, StackAllocator && salloc, Fn && fn, Arg ... arg) :
  89. #endif
  90. fiber{ policy,
  91. static_cast<fiber_properties*>(nullptr),
  92. std::allocator_arg, std::forward< StackAllocator >( salloc),
  93. std::forward< Fn >( fn), std::forward< Arg >( arg) ... } {
  94. }
  95. template< typename Fn,
  96. typename ... Arg,
  97. typename = detail::disable_overload< fiber, Fn >,
  98. typename = detail::disable_overload< launch, Fn >,
  99. typename = detail::disable_overload< std::allocator_arg_t, Fn >
  100. >
  101. #if BOOST_COMP_GNUC < 50000000
  102. explicit fiber( fiber_properties* properties, Fn && fn, Arg && ... arg) :
  103. #else
  104. fiber( fiber_properties* properties, Fn && fn, Arg ... arg) :
  105. #endif
  106. fiber{ launch::post,
  107. properties,
  108. std::allocator_arg, default_stack(),
  109. std::forward< Fn >( fn), std::forward< Arg >( arg) ... } {
  110. }
  111. template< typename Fn,
  112. typename ... Arg,
  113. typename = detail::disable_overload< fiber, Fn >
  114. >
  115. #if BOOST_COMP_GNUC < 50000000
  116. fiber( launch policy, fiber_properties* properties, Fn && fn, Arg && ... arg) :
  117. #else
  118. fiber( launch policy, fiber_properties* properties, Fn && fn, Arg ... arg) :
  119. #endif
  120. fiber{ policy,
  121. properties,
  122. std::allocator_arg, default_stack(),
  123. std::forward< Fn >( fn), std::forward< Arg >( arg) ... } {
  124. }
  125. template< typename StackAllocator,
  126. typename Fn,
  127. typename ... Arg
  128. >
  129. #if BOOST_COMP_GNUC < 50000000
  130. fiber( fiber_properties* properties, std::allocator_arg_t, StackAllocator && salloc, Fn && fn, Arg && ... arg) :
  131. #else
  132. fiber( fiber_properties* properties, std::allocator_arg_t, StackAllocator && salloc, Fn && fn, Arg ... arg) :
  133. #endif
  134. fiber{ launch::post,
  135. properties,
  136. std::allocator_arg, std::forward< StackAllocator >( salloc),
  137. std::forward< Fn >( fn), std::forward< Arg >( arg) ... } {
  138. }
  139. template< typename StackAllocator,
  140. typename Fn,
  141. typename ... Arg
  142. >
  143. #if BOOST_COMP_GNUC < 50000000
  144. fiber( launch policy, fiber_properties* properties, std::allocator_arg_t, StackAllocator && salloc, Fn && fn, Arg && ... arg) :
  145. #else
  146. fiber( launch policy, fiber_properties* properties, std::allocator_arg_t, StackAllocator && salloc, Fn && fn, Arg ... arg) :
  147. #endif
  148. impl_{ make_worker_context_with_properties( policy, properties, std::forward< StackAllocator >( salloc), std::forward< Fn >( fn), std::forward< Arg >( arg) ... ) } {
  149. start_();
  150. }
  151. ~fiber() {
  152. if ( joinable() ) {
  153. std::terminate();
  154. }
  155. }
  156. fiber( fiber const&) = delete;
  157. fiber & operator=( fiber const&) = delete;
  158. fiber( fiber && other) noexcept :
  159. impl_{} {
  160. swap( other);
  161. }
  162. fiber & operator=( fiber && other) noexcept {
  163. if ( joinable() ) {
  164. std::terminate();
  165. }
  166. if ( BOOST_UNLIKELY( this == & other) ) {
  167. return * this;
  168. }
  169. impl_.swap( other.impl_);
  170. return * this;
  171. }
  172. void swap( fiber & other) noexcept {
  173. impl_.swap( other.impl_);
  174. }
  175. id get_id() const noexcept {
  176. return impl_ ? impl_->get_id() : id();
  177. }
  178. bool joinable() const noexcept {
  179. return nullptr != impl_;
  180. }
  181. void join();
  182. void detach();
  183. template< typename PROPS >
  184. PROPS & properties() {
  185. auto props = impl_->get_properties();
  186. BOOST_ASSERT_MSG( props, "fiber::properties not set");
  187. return dynamic_cast< PROPS & >( * props );
  188. }
  189. };
  190. inline
  191. bool operator<( fiber const& l, fiber const& r) noexcept {
  192. return l.get_id() < r.get_id();
  193. }
  194. inline
  195. void swap( fiber & l, fiber & r) noexcept {
  196. return l.swap( r);
  197. }
  198. }}
  199. #ifdef _MSC_VER
  200. # pragma warning(pop)
  201. #endif
  202. #ifdef BOOST_HAS_ABI_HEADERS
  203. # include BOOST_ABI_SUFFIX
  204. #endif
  205. #endif // BOOST_FIBERS_FIBER_H