Changeset 9fe2fd7 in mainline for uspace/lib/cpp/include/__bits/thread/future.hpp
- Timestamp:
- 2019-07-24T11:44:40Z (5 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- a448937, f42ee6f
- Parents:
- 9fb280c (diff), 8c0b781 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)
links above to see all the changes relative to each parent. - git-author:
- Jaroslav Jindrak <Dzejrou@…> (2019-07-24 11:44:40)
- git-committer:
- GitHub <noreply@…> (2019-07-24 11:44:40)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/cpp/include/__bits/thread/future.hpp
r9fb280c r9fe2fd7 30 30 #define LIBCPP_BITS_THREAD_FUTURE 31 31 32 #include <__bits/thread/future_common.hpp> 33 #include <__bits/thread/shared_state.hpp> 34 #include <__bits/utility/forward_move.hpp> 32 35 #include <cassert> 33 #include <memory>34 #include <system_error>35 #include <type_traits>36 36 37 37 namespace std 38 38 { 39 39 /** 40 * 30.6 , futures:40 * 30.6.6, class template future: 41 41 */ 42 42 43 enum class future_errc 44 { // The 5001 start is to not collide with system_error's codes. 45 broken_promise = 5001, 46 future_already_retrieved, 47 promise_already_satisfied, 48 no_state 43 namespace aux 44 { 45 /** 46 * Note: Because of shared_future, this base class 47 * does implement copy constructor and copy 48 * assignment operator. This means that the 49 * children (std::future) need to delete this 50 * constructor and operator themselves. 51 */ 52 template<class R> 53 class future_base 54 { 55 public: 56 future_base() noexcept 57 : state_{nullptr} 58 { /* DUMMY BODY */ } 59 60 future_base(const future_base& rhs) 61 : state_{rhs.state_} 62 { 63 state_->increment(); 64 } 65 66 future_base(future_base&& rhs) noexcept 67 : state_{move(rhs.state_)} 68 { 69 rhs.state_ = nullptr; 70 } 71 72 future_base(aux::shared_state<R>* state) 73 : state_{state} 74 { 75 /** 76 * Note: This is a custom non-standard constructor that allows 77 * us to create a future directly from a shared state. This 78 * should never be a problem as aux::shared_state is a private 79 * type and future has no constructor templates. 80 */ 81 } 82 83 virtual ~future_base() 84 { 85 release_state_(); 86 } 87 88 future_base& operator=(const future_base& rhs) 89 { 90 release_state_(); 91 state_ = rhs.state_; 92 93 state_->increment(); 94 95 return *this; 96 } 97 98 future_base& operator=(future_base&& rhs) noexcept 99 { 100 release_state_(); 101 state_ = move(rhs.state_); 102 rhs.state_ = nullptr; 103 104 return *this; 105 } 106 107 bool valid() const noexcept 108 { 109 return state_ != nullptr; 110 } 111 112 void wait() const noexcept 113 { 114 assert(state_); 115 116 state_->wait(); 117 } 118 119 template<class Rep, class Period> 120 future_status 121 wait_for(const chrono::duration<Rep, Period>& rel_time) const 122 { 123 assert(state_); 124 125 return state_->wait_for(rel_time); 126 } 127 128 template<class Clock, class Duration> 129 future_status 130 wait_until( 131 const chrono::time_point<Clock, Duration>& abs_time 132 ) const 133 { 134 assert(state_); 135 136 return state_->wait_until(abs_time); 137 } 138 139 protected: 140 void release_state_() 141 { 142 if (!state_) 143 return; 144 145 /** 146 * Note: This is the 'release' move described in 147 * 30.6.4 (5). 148 * Last reference to state -> destroy state. 149 * Decrement refcount of state otherwise. 150 * Will not block, unless all following hold: 151 * 1) State was created by call to std::async. 152 * 2) State is not yet ready. 153 * 3) This was the last reference to the shared state. 154 */ 155 if (state_->decrement()) 156 { 157 /** 158 * The destroy call handles the special case 159 * when 1) - 3) hold. 160 */ 161 state_->destroy(); 162 delete state_; 163 state_ = nullptr; 164 } 165 } 166 167 aux::shared_state<R>* state_; 168 }; 169 } 170 171 template<class R> 172 class shared_future; 173 174 template<class R> 175 class future: public aux::future_base<aux::future_inner_t<R>> 176 { 177 friend class shared_future<R>; 178 179 public: 180 future() noexcept 181 : aux::future_base<aux::future_inner_t<R>>{} 182 { /* DUMMY BODY */ } 183 184 future(const future&) = delete; 185 186 future(future&& rhs) noexcept 187 : aux::future_base<aux::future_inner_t<R>>{move(rhs)} 188 { /* DUMMY BODY */ } 189 190 future(aux::shared_state<aux::future_inner_t<R>>* state) 191 : aux::future_base<aux::future_inner_t<R>>{state} 192 { /* DUMMY BODY */ } 193 194 future& operator=(const future&) = delete; 195 196 future& operator=(future&& rhs) noexcept = default; 197 198 shared_future<R> share() 199 { 200 return shared_future<R>{move(*this)}; 201 } 202 203 R get() 204 { 205 assert(this->state_); 206 207 this->wait(); 208 209 if (this->state_->has_exception()) 210 this->state_->throw_stored_exception(); 211 212 if constexpr (!is_same_v<R, void>) 213 { 214 if constexpr (is_reference_v<R>) 215 { 216 assert(this->state_->get()); 217 218 return *this->state_->get(); 219 } 220 else 221 return this->state_->get(); 222 } 223 } 224 225 /** 226 * Useful for testing as we can check some information 227 * otherwise unavailable to us without waiting, e.g. 228 * to check whether the state is ready, its reference 229 * count etc. 230 */ 231 aux::shared_state<aux::future_inner_t<R>>* __state() noexcept 232 { 233 return this->state_; 234 } 49 235 }; 50 51 enum class launch52 {53 async,54 deferred55 };56 57 enum class future_status58 {59 ready,60 timeout,61 deferred62 };63 64 /**65 * 30.6.2, error handling:66 */67 68 template<>69 struct is_error_code_enum<future_errc>: true_type70 { /* DUMMY BODY */ };71 72 error_code make_error_code(future_errc) noexcept;73 error_condition make_error_condition(future_errc) noexcept;74 75 const error_category& future_category() noexcept;76 77 /**78 * 30.6.3, class future_error:79 */80 81 class future_error: public logic_error82 {83 public:84 future_error(error_code ec);85 86 const error_code& code() const noexcept;87 88 private:89 error_code code_;90 };91 92 /**93 * 30.6.4, shared state:94 */95 96 template<class R>97 class promise98 {99 };100 101 template<class R>102 class promise<R&>103 {104 };105 106 template<>107 class promise<void>108 {109 };110 111 template<class R>112 void swap(promise<R>& lhs, promise<R>& rhs) noexcept113 {114 lhs.swap(rhs);115 }116 117 template<class R, class Alloc>118 struct uses_allocator<promise<R>, Alloc>: true_type119 { /* DUMMY BODY */ };120 121 template<class R>122 class future123 {124 };125 126 template<class R>127 class future<R&>128 {129 };130 131 template<>132 class future<void>133 {134 };135 136 template<class R>137 class shared_future138 {139 };140 141 template<class R>142 class shared_future<R&>143 {144 };145 146 template<>147 class shared_future<void>148 {149 };150 151 template<class>152 class packaged_task; // undefined153 154 template<class R, class... Args>155 class packaged_task<R(Args...)>156 {157 };158 159 template<class R, class... Args>160 void swap(packaged_task<R(Args...)>& lhs, packaged_task<R(Args...)>& rhs) noexcept161 {162 lhs.swap(rhs);163 };164 165 template<class R, class Alloc>166 struct uses_allocator<packaged_task<R>, Alloc>: true_type167 { /* DUMMY BODY */ };168 169 template<class F, class... Args>170 future<result_of_t<decay_t<F>(decay_t<Args>...)>>171 async(F&& f, Args&&... args)172 {173 // TODO: implement174 __unimplemented();175 }176 177 template<class F, class... Args>178 future<result_of_t<decay_t<F>(decay_t<Args>...)>>179 async(launch, F&& f, Args&&... args)180 {181 // TODO: implement182 __unimplemented();183 }184 236 } 185 237
Note:
See TracChangeset
for help on using the changeset viewer.