fiber.hpp 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  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. impl_{ make_worker_context( policy, std::forward< StackAllocator >( salloc), std::forward< Fn >( fn), std::forward< Arg >( arg) ... ) } {
  91. start_();
  92. }
  93. ~fiber() {
  94. if ( joinable() ) {
  95. std::terminate();
  96. }
  97. }
  98. fiber( fiber const&) = delete;
  99. fiber & operator=( fiber const&) = delete;
  100. fiber( fiber && other) noexcept :
  101. impl_{} {
  102. swap( other);
  103. }
  104. fiber & operator=( fiber && other) noexcept {
  105. if ( joinable() ) {
  106. std::terminate();
  107. }
  108. if ( BOOST_UNLIKELY( this == & other) ) {
  109. return * this;
  110. }
  111. impl_.swap( other.impl_);
  112. return * this;
  113. }
  114. void swap( fiber & other) noexcept {
  115. impl_.swap( other.impl_);
  116. }
  117. id get_id() const noexcept {
  118. return impl_ ? impl_->get_id() : id();
  119. }
  120. bool joinable() const noexcept {
  121. return nullptr != impl_;
  122. }
  123. void join();
  124. void detach();
  125. template< typename PROPS >
  126. PROPS & properties() {
  127. auto props = impl_->get_properties();
  128. BOOST_ASSERT_MSG( props, "fiber::properties not set");
  129. return dynamic_cast< PROPS & >( * props );
  130. }
  131. };
  132. inline
  133. bool operator<( fiber const& l, fiber const& r) noexcept {
  134. return l.get_id() < r.get_id();
  135. }
  136. inline
  137. void swap( fiber & l, fiber & r) noexcept {
  138. return l.swap( r);
  139. }
  140. }}
  141. #ifdef _MSC_VER
  142. # pragma warning(pop)
  143. #endif
  144. #ifdef BOOST_HAS_ABI_HEADERS
  145. # include BOOST_ABI_SUFFIX
  146. #endif
  147. #endif // BOOST_FIBERS_FIBER_H