Changeset 6e97265 in mainline for uspace/lib/cpp/include/__bits/thread/future.hpp
- Timestamp:
- 2019-06-30T14:37:40Z (6 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 3a29607
- Parents:
- d86c00f0
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/cpp/include/__bits/thread/future.hpp
rd86c00f0 r6e97265 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 <thread>36 #include <tuple>37 #include <type_traits>38 #include <utility>39 36 40 37 namespace std 41 38 { 42 39 /** 43 * 30.6, futures:44 */45 46 enum class future_errc47 { // The 5001 start is to not collide with system_error's codes.48 broken_promise = 5001,49 future_already_retrieved,50 promise_already_satisfied,51 no_state52 };53 54 enum class future_status55 {56 ready,57 timeout,58 deferred59 };60 61 /**62 * 30.6.2, error handling:63 */64 65 template<>66 struct is_error_code_enum<future_errc>: true_type67 { /* DUMMY BODY */ };68 69 error_code make_error_code(future_errc) noexcept;70 error_condition make_error_condition(future_errc) noexcept;71 72 const error_category& future_category() noexcept;73 74 /**75 * 30.6.3, class future_error:76 */77 78 class future_error: public logic_error79 {80 public:81 future_error(error_code ec);82 83 const error_code& code() const noexcept;84 const char* what() const noexcept;85 86 private:87 error_code code_;88 };89 90 /**91 40 * 30.6.6, class template future: 92 41 */ 93 42 43 namespace aux 44 { 45 template<class R> 46 class future_base 47 { 48 public: 49 future_base() noexcept 50 : state_{nullptr} 51 { /* DUMMY BODY */ } 52 53 future_base(const future_base&) = delete; 54 55 future_base(future_base&& rhs) noexcept 56 : state_{std::move(rhs.state_)} 57 { 58 rhs.state_ = nullptr; 59 } 60 61 future_base(aux::shared_state<R>* state) 62 : state_{state} 63 { 64 /** 65 * Note: This is a custom non-standard constructor that allows 66 * us to create a future directly from a shared state. This 67 * should never be a problem as aux::shared_state is a private 68 * type and future has no constructor templates. 69 */ 70 } 71 72 virtual ~future_base() 73 { 74 release_state_(); 75 } 76 77 future_base& operator=(const future_base&) = delete; 78 79 future_base& operator=(future_base&& rhs) noexcept 80 { 81 release_state_(); 82 state_ = std::move(rhs.state_); 83 rhs.state_ = nullptr; 84 } 85 86 bool valid() const noexcept 87 { 88 return state_ != nullptr; 89 } 90 91 void wait() const noexcept 92 { 93 assert(state_); 94 95 state_->wait(); 96 } 97 98 template<class Rep, class Period> 99 future_status 100 wait_for(const chrono::duration<Rep, Period>& rel_time) const 101 { 102 assert(state_); 103 104 return state_->wait_for(rel_time); 105 } 106 107 template<class Clock, class Duration> 108 future_status 109 wait_until( 110 const chrono::time_point<Clock, Duration>& abs_time 111 ) const 112 { 113 assert(state_); 114 115 return state_->wait_until(abs_time); 116 } 117 118 protected: 119 void release_state_() 120 { 121 if (!state_) 122 return; 123 124 /** 125 * Note: This is the 'release' move described in 126 * 30.6.4 (5). 127 * Last reference to state -> destroy state. 128 * Decrement refcount of state otherwise. 129 * Will not block, unless all following hold: 130 * 1) State was created by call to std::async. 131 * 2) State is not yet ready. 132 * 3) This was the last reference to the shared state. 133 */ 134 if (state_->decrement()) 135 { 136 /** 137 * The destroy call handles the special case 138 * when 1) - 3) hold. 139 */ 140 state_->destroy(); 141 delete state_; 142 state_ = nullptr; 143 } 144 } 145 146 aux::shared_state<R>* state_; 147 }; 148 } 149 94 150 template<class R> 95 151 class shared_future; 96 152 97 153 template<class R> 98 class future 154 class future: public aux::future_base<R> 99 155 { 100 156 public: 101 157 future() noexcept 102 : state_{nullptr}158 : aux::future_base<R>{} 103 159 { /* DUMMY BODY */ } 104 160 … … 106 162 107 163 future(future&& rhs) noexcept 108 : state_{std::move(rhs.state_)} 109 { 110 rhs.state_ = nullptr; 111 } 164 : aux::future_base<R>{std::move(rhs.state_)} 165 { /* DUMMY BODY */ } 112 166 113 167 future(aux::shared_state<R>* state) 114 : state_{state} 115 { 116 /** 117 * Note: This is a custom non-standard constructor that allows 118 * us to create a future directly from a shared state. This 119 * should never be a problem as aux::shared_state is a private 120 * type and future has no constructor templates. 121 */ 122 } 123 124 ~future() 125 { 126 release_state_(); 127 } 128 129 future& operator=(const future) = delete; 168 : aux::future_base<R>{state} 169 { /* DUMMY BODY */ } 170 171 future& operator=(const future&) = delete; 130 172 131 173 future& operator=(future&& rhs) noexcept 132 174 { 133 release_state_(); 134 state_ = std::move(rhs.state_); 135 rhs.state_ = nullptr; 175 return aux::future_base<R>::operator=(std::move(rhs)); 136 176 } 137 177 … … 143 183 R get() 144 184 { 145 assert( state_);146 147 wait();148 149 if ( state_->has_exception())150 state_->throw_stored_exception();151 auto res = std::move( state_->get());152 153 release_state_();185 assert(this->state_); 186 187 this->wait(); 188 189 if (this->state_->has_exception()) 190 this->state_->throw_stored_exception(); 191 auto res = std::move(this->state_->get()); 192 193 this->release_state_(); 154 194 155 195 return res; 156 196 } 157 158 bool valid() const noexcept159 {160 return state_ != nullptr;161 }162 163 void wait() const noexcept164 {165 assert(state_);166 167 state_->wait();168 }169 170 template<class Rep, class Period>171 future_status wait_for(const chrono::duration<Rep, Period>& rel_time) const172 {173 assert(state_);174 175 return state_->wait_for(rel_time);176 }177 178 template<class Clock, class Duration>179 future_status wait_until(const chrono::time_point<Clock, Duration>& abs_time) const180 {181 assert(state_);182 183 return state_->wait_until(abs_time);184 }185 186 private:187 void release_state_()188 {189 if (!state_)190 return;191 192 /**193 * Note: This is the 'release' move described in194 * 30.6.4 (5).195 * Last reference to state -> destroy state.196 * Decrement refcount of state otherwise.197 * Will not block, unless all following hold:198 * 1) State was created by call to std::async.199 * 2) State is not yet ready.200 * 3) This was the last reference to the shared state.201 */202 if (state_->decrement())203 {204 /**205 * The destroy call handles the special case206 * when 1) - 3) hold.207 */208 state_->destroy();209 delete state_;210 state_ = nullptr;211 }212 }213 214 aux::shared_state<R>* state_;215 197 }; 216 198
Note:
See TracChangeset
for help on using the changeset viewer.