]>
Commit | Line | Data |
---|---|---|
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_ALGO_ALGORITHM_H | |
7 | #define BOOST_FIBERS_ALGO_ALGORITHM_H | |
8 | ||
9 | #include <cstddef> | |
10 | #include <chrono> | |
11 | ||
12 | #include <boost/config.hpp> | |
13 | #include <boost/assert.hpp> | |
14 | ||
15 | #include <boost/fiber/properties.hpp> | |
16 | #include <boost/fiber/detail/config.hpp> | |
17 | ||
18 | #ifdef BOOST_HAS_ABI_HEADERS | |
19 | # include BOOST_ABI_PREFIX | |
20 | #endif | |
21 | ||
22 | namespace boost { | |
23 | namespace fibers { | |
24 | ||
25 | class context; | |
26 | ||
27 | namespace algo { | |
28 | ||
29 | struct BOOST_FIBERS_DECL algorithm { | |
30 | virtual ~algorithm() {} | |
31 | ||
32 | virtual void awakened( context *) noexcept = 0; | |
33 | ||
34 | virtual context * pick_next() noexcept = 0; | |
35 | ||
36 | virtual bool has_ready_fibers() const noexcept = 0; | |
37 | ||
38 | virtual void suspend_until( std::chrono::steady_clock::time_point const&) noexcept = 0; | |
39 | ||
40 | virtual void notify() noexcept = 0; | |
41 | }; | |
42 | ||
43 | class BOOST_FIBERS_DECL algorithm_with_properties_base : public algorithm { | |
44 | public: | |
45 | // called by fiber_properties::notify() -- don't directly call | |
46 | virtual void property_change_( context * f, fiber_properties * props) noexcept = 0; | |
47 | ||
48 | protected: | |
49 | static fiber_properties* get_properties( context * f) noexcept; | |
50 | static void set_properties( context * f, fiber_properties * p) noexcept; | |
51 | }; | |
52 | ||
53 | template< typename PROPS > | |
54 | struct algorithm_with_properties : public algorithm_with_properties_base { | |
55 | typedef algorithm_with_properties_base super; | |
56 | ||
57 | // Mark this override 'final': algorithm_with_properties subclasses | |
58 | // must override awakened() with properties parameter instead. Otherwise | |
59 | // you'd have to remember to start every subclass awakened() override | |
60 | // with: algorithm_with_properties<PROPS>::awakened(fb); | |
61 | virtual void awakened( context * f) noexcept override final { | |
62 | fiber_properties * props = super::get_properties( f); | |
63 | if ( nullptr == props) { | |
64 | // TODO: would be great if PROPS could be allocated on the new | |
65 | // fiber's stack somehow | |
66 | props = new_properties( f); | |
67 | // It is not good for new_properties() to return 0. | |
68 | BOOST_ASSERT_MSG(props, "new_properties() must return non-NULL"); | |
69 | // new_properties() must return instance of (a subclass of) PROPS | |
70 | BOOST_ASSERT_MSG( dynamic_cast< PROPS * >( props), | |
71 | "new_properties() must return properties class"); | |
72 | super::set_properties( f, props); | |
73 | } | |
74 | // Set algo_ again every time this fiber becomes READY. That | |
75 | // handles the case of a fiber migrating to a new thread with a new | |
76 | // algorithm subclass instance. | |
77 | props->set_algorithm( this); | |
78 | ||
79 | // Okay, now forward the call to subclass override. | |
80 | awakened( f, properties(f) ); | |
81 | } | |
82 | ||
83 | // subclasses override this method instead of the original awakened() | |
84 | virtual void awakened( context *, PROPS& ) noexcept = 0; | |
85 | ||
86 | // used for all internal calls | |
87 | PROPS & properties( context * f) noexcept { | |
88 | return static_cast< PROPS & >( * super::get_properties( f) ); | |
89 | } | |
90 | ||
91 | // override this to be notified by PROPS::notify() | |
92 | virtual void property_change( context * f, PROPS & props) noexcept { | |
93 | } | |
94 | ||
95 | // implementation for algorithm_with_properties_base method | |
96 | void property_change_( context * f, fiber_properties * props ) noexcept override final { | |
97 | property_change( f, * static_cast< PROPS * >( props) ); | |
98 | } | |
99 | ||
100 | // Override this to customize instantiation of PROPS, e.g. use a different | |
101 | // allocator. Each PROPS instance is associated with a particular | |
102 | // context. | |
103 | virtual fiber_properties * new_properties( context * f) { | |
104 | return new PROPS( f); | |
105 | } | |
106 | }; | |
107 | ||
108 | }}} | |
109 | ||
110 | #ifdef BOOST_HAS_ABI_HEADERS | |
111 | # include BOOST_ABI_SUFFIX | |
112 | #endif | |
113 | ||
114 | #endif // BOOST_FIBERS_ALGO_ALGORITHM_H |