]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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/execution_context.hpp> | |
17 | #include <boost/intrusive/list.hpp> | |
18 | #include <boost/intrusive_ptr.hpp> | |
19 | #include <boost/intrusive/set.hpp> | |
20 | ||
21 | #include <boost/fiber/algo/algorithm.hpp> | |
22 | #include <boost/fiber/context.hpp> | |
23 | #include <boost/fiber/detail/config.hpp> | |
24 | #include <boost/fiber/detail/data.hpp> | |
25 | #include <boost/fiber/detail/spinlock.hpp> | |
26 | ||
27 | #ifdef BOOST_HAS_ABI_HEADERS | |
28 | # include BOOST_ABI_PREFIX | |
29 | #endif | |
30 | ||
31 | #ifdef _MSC_VER | |
32 | # pragma warning(push) | |
33 | # pragma warning(disable:4251) | |
34 | #endif | |
35 | ||
36 | namespace boost { | |
37 | namespace fibers { | |
38 | ||
39 | class BOOST_FIBERS_DECL scheduler { | |
40 | public: | |
41 | struct timepoint_less { | |
42 | bool operator()( context const& l, context const& r) const noexcept { | |
43 | return l.tp_ < r.tp_; | |
44 | } | |
45 | }; | |
46 | ||
47 | typedef intrusive::list< | |
48 | context, | |
49 | intrusive::member_hook< | |
50 | context, detail::ready_hook, & context::ready_hook_ >, | |
51 | intrusive::constant_time_size< false > > ready_queue_t; | |
52 | private: | |
53 | typedef std::vector< context * > remote_ready_queue_t; | |
54 | typedef intrusive::set< | |
55 | context, | |
56 | intrusive::member_hook< | |
57 | context, detail::sleep_hook, & context::sleep_hook_ >, | |
58 | intrusive::constant_time_size< false >, | |
59 | intrusive::compare< timepoint_less > > sleep_queue_t; | |
60 | typedef intrusive::list< | |
61 | context, | |
62 | intrusive::member_hook< | |
63 | context, detail::terminated_hook, & context::terminated_hook_ >, | |
64 | intrusive::constant_time_size< false > > terminated_queue_t; | |
65 | typedef intrusive::list< | |
66 | context, | |
67 | intrusive::member_hook< | |
68 | context, detail::worker_hook, & context::worker_hook_ >, | |
69 | intrusive::constant_time_size< false > > worker_queue_t; | |
70 | ||
71 | std::unique_ptr< algo::algorithm > algo_; | |
72 | context * main_ctx_{ nullptr }; | |
73 | intrusive_ptr< context > dispatcher_ctx_{}; | |
74 | // worker-queue contains all context' mananged by this scheduler | |
75 | // except main-context and dispatcher-context | |
76 | // unlink happens on destruction of a context | |
77 | worker_queue_t worker_queue_{}; | |
78 | // terminated-queue contains context' which have been terminated | |
79 | terminated_queue_t terminated_queue_{}; | |
80 | // remote ready-queue contains context' signaled by schedulers | |
81 | // running in other threads | |
82 | remote_ready_queue_t remote_ready_queue_{}; | |
83 | // sleep-queue cotnains context' whic hahve been called | |
84 | // scheduler::wait_until() | |
85 | sleep_queue_t sleep_queue_{}; | |
86 | bool shutdown_{ false }; | |
87 | std::mutex remote_ready_mtx_{}; | |
88 | ||
89 | context * get_next_() noexcept; | |
90 | ||
91 | void release_terminated_() noexcept; | |
92 | ||
93 | void remote_ready2ready_() noexcept; | |
94 | ||
95 | void sleep2ready_() noexcept; | |
96 | ||
97 | public: | |
98 | scheduler() noexcept; | |
99 | ||
100 | scheduler( scheduler const&) = delete; | |
101 | scheduler & operator=( scheduler const&) = delete; | |
102 | ||
103 | virtual ~scheduler(); | |
104 | ||
105 | void set_ready( context *) noexcept; | |
106 | ||
107 | void set_remote_ready( context *) noexcept; | |
108 | ||
109 | #if (BOOST_EXECUTION_CONTEXT==1) | |
110 | void dispatch() noexcept; | |
111 | ||
112 | void set_terminated( context *) noexcept; | |
113 | #else | |
114 | boost::context::execution_context< detail::data_t * > dispatch() noexcept; | |
115 | ||
116 | boost::context::execution_context< detail::data_t * > set_terminated( context *) noexcept; | |
117 | #endif | |
118 | ||
119 | void yield( context *) noexcept; | |
120 | ||
121 | bool wait_until( context *, | |
122 | std::chrono::steady_clock::time_point const&) noexcept; | |
123 | bool wait_until( context *, | |
124 | std::chrono::steady_clock::time_point const&, | |
125 | detail::spinlock_lock &) noexcept; | |
126 | ||
127 | void suspend() noexcept; | |
128 | void suspend( detail::spinlock_lock &) noexcept; | |
129 | ||
130 | bool has_ready_fibers() const noexcept; | |
131 | ||
132 | void set_algo( std::unique_ptr< algo::algorithm >) noexcept; | |
133 | ||
134 | void attach_main_context( context *) noexcept; | |
135 | ||
136 | void attach_dispatcher_context( intrusive_ptr< context >) noexcept; | |
137 | ||
138 | void attach_worker_context( context *) noexcept; | |
139 | ||
140 | void detach_worker_context( context *) noexcept; | |
141 | }; | |
142 | ||
143 | }} | |
144 | ||
145 | #ifdef _MSC_VER | |
146 | # pragma warning(pop) | |
147 | #endif | |
148 | ||
149 | #ifdef BOOST_HAS_ABI_HEADERS | |
150 | # include BOOST_ABI_SUFFIX | |
151 | #endif | |
152 | ||
153 | #endif // BOOST_FIBERS_FIBER_MANAGER_H |