]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/fiber/future/packaged_task.hpp
update sources to v12.2.3
[ceph.git] / ceph / src / boost / boost / fiber / future / packaged_task.hpp
1
2 // Copyright Oliver Kowalke 2013.
3 // Distributed under the Boost Software License, Version 1.0.
4 // (See accompanying file LICENSE_1_0.txt or copy at
5 // http://www.boost.org/LICENSE_1_0.txt)
6
7 #ifndef BOOST_FIBERS_PACKAGED_TASK_HPP
8 #define BOOST_FIBERS_PACKAGED_TASK_HPP
9
10 #include <algorithm>
11 #include <memory>
12 #include <type_traits>
13 #include <utility>
14
15 #include <boost/config.hpp>
16
17 #include <boost/fiber/detail/disable_overload.hpp>
18 #include <boost/fiber/exceptions.hpp>
19 #include <boost/fiber/future/detail/task_base.hpp>
20 #include <boost/fiber/future/detail/task_object.hpp>
21 #include <boost/fiber/future/future.hpp>
22
23 namespace boost {
24 namespace fibers {
25
26 template< typename Signature >
27 class packaged_task;
28
29 template< typename R, typename ... Args >
30 class packaged_task< R( Args ... ) > {
31 private:
32 typedef typename detail::task_base< R, Args ... >::ptr_type ptr_type;
33
34 bool obtained_{ false };
35 ptr_type task_{};
36
37 public:
38 packaged_task() = default;
39
40 template< typename Fn,
41 typename = detail::disable_overload< packaged_task, Fn >
42 >
43 explicit packaged_task( Fn && fn) :
44 packaged_task{ std::allocator_arg,
45 std::allocator< packaged_task >{},
46 std::forward< Fn >( fn) } {
47 }
48
49 template< typename Fn,
50 typename Allocator
51 >
52 explicit packaged_task( std::allocator_arg_t, Allocator const& alloc, Fn && fn) {
53 typedef detail::task_object<
54 typename std::decay< Fn >::type, Allocator, R, Args ...
55 > object_type;
56 typedef std::allocator_traits<
57 typename object_type::allocator_type
58 > traits_type;
59 typedef pointer_traits< typename traits_type::pointer > ptrait_type;
60
61 typename object_type::allocator_type a{ alloc };
62 typename traits_type::pointer ptr{ traits_type::allocate( a, 1) };
63 typename ptrait_type::element_type* p = boost::to_address(ptr);
64 try {
65 traits_type::construct( a, p, a, std::forward< Fn >( fn) );
66 } catch (...) {
67 traits_type::deallocate( a, ptr, 1);
68 throw;
69 }
70 task_.reset(p);
71 }
72
73 ~packaged_task() {
74 if ( task_) {
75 task_->owner_destroyed();
76 }
77 }
78
79 packaged_task( packaged_task const&) = delete;
80 packaged_task & operator=( packaged_task const&) = delete;
81
82 packaged_task( packaged_task && other) noexcept :
83 obtained_{ other.obtained_ },
84 task_{ std::move( other.task_) } {
85 other.obtained_ = false;
86 }
87
88 packaged_task & operator=( packaged_task && other) noexcept {
89 if ( BOOST_LIKELY( this != & other) ) {
90 packaged_task tmp{ std::move( other) };
91 swap( tmp);
92 }
93 return * this;
94 }
95
96 void swap( packaged_task & other) noexcept {
97 std::swap( obtained_, other.obtained_);
98 task_.swap( other.task_);
99 }
100
101 bool valid() const noexcept {
102 return nullptr != task_.get();
103 }
104
105 future< R > get_future() {
106 if ( obtained_) {
107 throw future_already_retrieved{};
108 }
109 if ( BOOST_UNLIKELY( ! valid() ) ) {
110 throw packaged_task_uninitialized{};
111 }
112 obtained_ = true;
113 return future< R >{
114 boost::static_pointer_cast< detail::shared_state< R > >( task_) };
115 }
116
117 void operator()( Args ... args) {
118 if ( BOOST_UNLIKELY( ! valid() ) ) {
119 throw packaged_task_uninitialized{};
120 }
121 task_->run( std::forward< Args >( args) ... );
122 }
123
124 void reset() {
125 if ( BOOST_UNLIKELY( ! valid() ) ) {
126 throw packaged_task_uninitialized{};
127 }
128 packaged_task tmp;
129 tmp.task_ = task_;
130 task_ = tmp.task_->reset();
131 obtained_ = false;
132 }
133 };
134
135 template< typename Signature >
136 void swap( packaged_task< Signature > & l, packaged_task< Signature > & r) noexcept {
137 l.swap( r);
138 }
139
140 }}
141
142 #endif // BOOST_FIBERS_PACKAGED_TASK_HPP