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 6 #ifndef BOOST_FIBERS_FIBER_MANAGER_H 7 #define BOOST_FIBERS_FIBER_MANAGER_H 8 9 #include <chrono> 10 #include <functional> 11 #include <memory> 12 #include <mutex> 13 #include <vector> 14 15 #include <boost/config.hpp> 16 #include <boost/context/fiber.hpp> 17 #include <boost/intrusive/list.hpp> 18 #include <boost/intrusive_ptr.hpp> 19 #include <boost/intrusive/set.hpp> 20 #include <boost/intrusive/slist.hpp> 21 22 #include <boost/fiber/algo/algorithm.hpp> 23 #include <boost/fiber/context.hpp> 24 #include <boost/fiber/detail/config.hpp> 25 #include <boost/fiber/detail/data.hpp> 26 #include <boost/fiber/detail/spinlock.hpp> 27 28 #ifdef BOOST_HAS_ABI_HEADERS 29 # include BOOST_ABI_PREFIX 30 #endif 31 32 #ifdef _MSC_VER 33 # pragma warning(push) 34 # pragma warning(disable:4251) 35 #endif 36 37 namespace boost { 38 namespace fibers { 39 40 class BOOST_FIBERS_DECL scheduler { 41 public: 42 struct timepoint_less { operator ()boost::fibers::scheduler::timepoint_less43 bool operator()( context const& l, context const& r) const noexcept { 44 return l.tp_ < r.tp_; 45 } 46 }; 47 48 typedef intrusive::list< 49 context, 50 intrusive::member_hook< 51 context, detail::ready_hook, & context::ready_hook_ >, 52 intrusive::constant_time_size< false > 53 > ready_queue_type; 54 private: 55 typedef intrusive::multiset< 56 context, 57 intrusive::member_hook< 58 context, detail::sleep_hook, & context::sleep_hook_ >, 59 intrusive::constant_time_size< false >, 60 intrusive::compare< timepoint_less > 61 > sleep_queue_type; 62 typedef intrusive::list< 63 context, 64 intrusive::member_hook< 65 context, detail::worker_hook, & context::worker_hook_ >, 66 intrusive::constant_time_size< false > 67 > worker_queue_type; 68 typedef intrusive::slist< 69 context, 70 intrusive::member_hook< 71 context, detail::terminated_hook, & context::terminated_hook_ >, 72 intrusive::linear< true >, 73 intrusive::cache_last< true > 74 > terminated_queue_type; 75 typedef intrusive::slist< 76 context, 77 intrusive::member_hook< 78 context, detail::remote_ready_hook, & context::remote_ready_hook_ >, 79 intrusive::linear< true >, 80 intrusive::cache_last< true > 81 > remote_ready_queue_type; 82 83 #if ! defined(BOOST_FIBERS_NO_ATOMICS) 84 // remote ready-queue contains context' signaled by schedulers 85 // running in other threads 86 detail::spinlock remote_ready_splk_{}; 87 remote_ready_queue_type remote_ready_queue_{}; 88 #endif 89 algo::algorithm::ptr_t algo_; 90 // sleep-queue contains context' which have been called 91 // scheduler::wait_until() 92 sleep_queue_type sleep_queue_{}; 93 // worker-queue contains all context' mananged by this scheduler 94 // except main-context and dispatcher-context 95 // unlink happens on destruction of a context 96 worker_queue_type worker_queue_{}; 97 // terminated-queue contains context' which have been terminated 98 terminated_queue_type terminated_queue_{}; 99 intrusive_ptr< context > dispatcher_ctx_{}; 100 context * main_ctx_{ nullptr }; 101 bool shutdown_{ false }; 102 103 void release_terminated_() noexcept; 104 105 #if ! defined(BOOST_FIBERS_NO_ATOMICS) 106 void remote_ready2ready_() noexcept; 107 #endif 108 109 void sleep2ready_() noexcept; 110 111 public: 112 scheduler() noexcept; 113 114 scheduler( scheduler const&) = delete; 115 scheduler & operator=( scheduler const&) = delete; 116 117 virtual ~scheduler(); 118 119 void schedule( context *) noexcept; 120 121 #if ! defined(BOOST_FIBERS_NO_ATOMICS) 122 void schedule_from_remote( context *) noexcept; 123 #endif 124 125 boost::context::fiber dispatch() noexcept; 126 127 boost::context::fiber terminate( detail::spinlock_lock &, context *) noexcept; 128 129 void yield( context *) noexcept; 130 131 bool wait_until( context *, 132 std::chrono::steady_clock::time_point const&) noexcept; 133 bool wait_until( context *, 134 std::chrono::steady_clock::time_point const&, 135 detail::spinlock_lock &) noexcept; 136 137 void suspend() noexcept; 138 void suspend( detail::spinlock_lock &) noexcept; 139 140 bool has_ready_fibers() const noexcept; 141 142 void set_algo( algo::algorithm::ptr_t) noexcept; 143 144 void attach_main_context( context *) noexcept; 145 146 void attach_dispatcher_context( intrusive_ptr< context >) noexcept; 147 148 void attach_worker_context( context *) noexcept; 149 150 void detach_worker_context( context *) noexcept; 151 }; 152 153 }} 154 155 #ifdef _MSC_VER 156 # pragma warning(pop) 157 #endif 158 159 #ifdef BOOST_HAS_ABI_HEADERS 160 # include BOOST_ABI_SUFFIX 161 #endif 162 163 #endif // BOOST_FIBERS_FIBER_MANAGER_H 164