]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/fiber/include/boost/fiber/future/packaged_task.hpp
bump version to 12.2.2-pve1
[ceph.git] / ceph / src / boost / libs / fiber / include / 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/convert.hpp>
18 #include <boost/fiber/detail/disable_overload.hpp>
19 #include <boost/fiber/exceptions.hpp>
20 #include <boost/fiber/future/detail/task_base.hpp>
21 #include <boost/fiber/future/detail/task_object.hpp>
22 #include <boost/fiber/future/future.hpp>
23
24 namespace boost {
25 namespace fibers {
26
27 template< typename Signature >
28 class packaged_task;
29
30 template< typename R, typename ... Args >
31 class packaged_task< R( Args ... ) > {
32 private:
33 typedef typename detail::task_base< R, Args ... >::ptr_t ptr_t;
34
35 bool obtained_{ false };
36 ptr_t task_{};
37
38 public:
39 constexpr packaged_task() noexcept = default;
40
41 template< typename Fn,
42 typename = detail::disable_overload< packaged_task, Fn >
43 >
44 explicit packaged_task( Fn && fn) :
45 packaged_task{ std::allocator_arg,
46 std::allocator< packaged_task >{},
47 std::forward< Fn >( fn) } {
48 }
49
50 template< typename Fn,
51 typename Allocator
52 >
53 explicit packaged_task( std::allocator_arg_t, Allocator const& alloc, Fn && fn) {
54 typedef detail::task_object<
55 typename std::decay< Fn >::type, Allocator, R, Args ...
56 > object_t;
57 typedef std::allocator_traits<
58 typename object_t::allocator_t
59 > traits_t;
60
61 typename object_t::allocator_t a{ alloc };
62 typename traits_t::pointer ptr{ traits_t::allocate( a, 1) };
63 try {
64 traits_t::construct( a, ptr, a, std::forward< Fn >( fn) );
65 } catch (...) {
66 traits_t::deallocate( a, ptr, 1);
67 throw;
68 }
69 task_.reset( convert( ptr) );
70 }
71
72 ~packaged_task() {
73 if ( task_) {
74 task_->owner_destroyed();
75 }
76 }
77
78 packaged_task( packaged_task const&) = delete;
79 packaged_task & operator=( packaged_task const&) = delete;
80
81 packaged_task( packaged_task && other) noexcept :
82 obtained_{ other.obtained_ },
83 task_{ std::move( other.task_) } {
84 other.obtained_ = false;
85 }
86
87 packaged_task & operator=( packaged_task && other) noexcept {
88 if ( this == & other) return * this;
89 packaged_task tmp{ std::move( other) };
90 swap( tmp);
91 return * this;
92 }
93
94 void swap( packaged_task & other) noexcept {
95 std::swap( obtained_, other.obtained_);
96 task_.swap( other.task_);
97 }
98
99 bool valid() const noexcept {
100 return nullptr != task_.get();
101 }
102
103 future< R > get_future() {
104 if ( obtained_) {
105 throw future_already_retrieved{};
106 }
107 if ( ! valid() ) {
108 throw packaged_task_uninitialized{};
109 }
110 obtained_ = true;
111 return future< R >{
112 boost::static_pointer_cast< detail::shared_state< R > >( task_) };
113 }
114
115 void operator()( Args ... args) {
116 if ( ! valid() ) {
117 throw packaged_task_uninitialized{};
118 }
119 task_->run( std::forward< Args >( args) ... );
120 }
121
122 void reset() {
123 if ( ! valid() ) {
124 throw packaged_task_uninitialized{};
125 }
126 packaged_task tmp;
127 tmp.task_ = task_;
128 task_ = tmp.task_->reset();
129 obtained_ = false;
130 }
131 };
132
133 template< typename Signature >
134 void swap( packaged_task< Signature > & l, packaged_task< Signature > & r) noexcept {
135 l.swap( r);
136 }
137
138 }}
139
140 #endif // BOOST_FIBERS_PACKAGED_TASK_HPP