Changeset cf279270 in mainline
- Timestamp:
- 2019-07-01T12:23:10Z (6 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 396b234
- Parents:
- 87efcb1
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/cpp/include/__bits/thread/promise.hpp
r87efcb1 rcf279270 41 41 */ 42 42 43 namespace aux 44 { 45 template<class R> 46 class promise_base 47 { 48 public: 49 promise_base() 50 : state_{new aux::shared_state<R>{}} 51 { /* DUMMY BODY */ } 52 53 template<class Allocator> 54 promise_base(allocator_arg_t, const Allocator& a) 55 : promise_base{} 56 { 57 // TODO: Use the allocator. 58 } 59 60 promise_base(promise_base&& rhs) noexcept 61 : state_{} 62 { 63 state_ = rhs.state_; 64 rhs.state_ = nullptr; 65 } 66 67 promise_base(const promise_base&) = delete; 68 69 virtual ~promise_base() 70 { 71 this->abandon_state_(); 72 } 73 74 promise_base& operator=(promise_base&& rhs) noexcept 75 { 76 abandon_state_(); 77 promise_base{std::move(rhs)}.swap(*this); 78 79 return *this; 80 } 81 82 promise_base& operator=(const promise_base&) = delete; 83 84 void swap(promise_base& other) noexcept 85 { 86 std::swap(state_, other.state_); 87 } 88 89 future<R> get_future() 90 { 91 return future<R>{state_}; 92 } 93 94 void set_exception(exception_ptr ptr) 95 { 96 assert(state_); 97 98 state_->set_exception(ptr); 99 } 100 101 void set_exception_at_thread_exit(exception_ptr) 102 { 103 // TODO: No exception handling, no-op at this time. 104 } 105 106 protected: 107 void abandon_state_() 108 { 109 /** 110 * Note: This is the 'abandon' move described in 111 * 30.6.4 (7). 112 * 1) If state is not ready: 113 * a) Store exception of type future_error with 114 * error condition broken_promise. 115 * b) Mark state as ready. 116 * 2) Release the state. 117 */ 118 } 119 120 aux::shared_state<R>* state_; 121 }; 122 } 123 43 124 template<class R> 44 class promise 125 class promise: public aux::promise_base<R> 45 126 { 46 127 public: 47 128 promise() 48 : state_{new aux::shared_state<R>{}}129 : aux::promise_base<R>{} 49 130 { /* DUMMY BODY */ } 50 131 51 132 template<class Allocator> 52 133 promise(allocator_arg_t, const Allocator& a) 53 : promise{}134 : aux::promise_base<R>{} 54 135 { 55 136 // TODO: Use the allocator. … … 57 138 58 139 promise(promise&& rhs) noexcept 59 : state_{} 60 { 61 state_ = rhs.state_; 62 rhs.state_ = nullptr; 63 } 140 : aux::promise_base<R>{move(rhs)} 141 { /* DUMMY BODY */ } 64 142 65 143 promise(const promise&) = delete; 66 144 67 ~promise() 68 { 69 abandon_state_(); 70 } 71 72 promise& operator=(promise&& rhs) noexcept 73 { 74 abandon_state_(); 75 promise{std::move(rhs)}.swap(*this); 76 } 145 ~promise() override = default; 146 147 promise& operator=(promise&& rhs) noexcept = default; 77 148 78 149 promise& operator=(const promise&) = delete; 79 150 80 void swap(promise& other) noexcept81 {82 std::swap(state_, other.state_);83 }84 85 future<R> get_future()86 {87 return future<R>{state_};88 }89 90 151 void set_value(const R& val) 91 152 { 92 if (! state_)93 throw future_error{make_error_code(future_errc::no_state)}; 94 if ( state_->is_set())95 { 96 throw future_error{ 97 make_error_code(future_errc::promise_already_satisfied) 98 }; 99 } 100 101 state_->set_value(val, true);153 if (!this->state_) 154 throw future_error{make_error_code(future_errc::no_state)}; 155 if (this->state_->is_set()) 156 { 157 throw future_error{ 158 make_error_code(future_errc::promise_already_satisfied) 159 }; 160 } 161 162 this->state_->set_value(val, true); 102 163 } 103 164 104 165 void set_value(R&& val) 105 166 { 106 if (!state_) 107 throw future_error{make_error_code(future_errc::no_state)}; 108 if (state_->is_set()) 109 { 110 throw future_error{ 111 make_error_code(future_errc::promise_already_satisfied) 112 }; 113 } 114 115 state_->set_value(std::forward<R>(val), true); 116 } 117 118 void set_exception(exception_ptr ptr) 119 { 120 assert(state_); 121 122 state_->set_exception(ptr); 167 if (!this->state_) 168 throw future_error{make_error_code(future_errc::no_state)}; 169 if (this->state_->is_set()) 170 { 171 throw future_error{ 172 make_error_code(future_errc::promise_already_satisfied) 173 }; 174 } 175 176 this->state_->set_value(std::forward<R>(val), true); 123 177 } 124 178 125 179 void set_value_at_thread_exit(const R& val) 126 180 { 127 if (! state_)128 throw future_error{make_error_code(future_errc::no_state)}; 129 if ( state_->is_set())130 { 131 throw future_error{ 132 make_error_code(future_errc::promise_already_satisfied) 133 }; 134 } 135 136 state_->set_value(val, false);181 if (!this->state_) 182 throw future_error{make_error_code(future_errc::no_state)}; 183 if (this->state_->is_set()) 184 { 185 throw future_error{ 186 make_error_code(future_errc::promise_already_satisfied) 187 }; 188 } 189 190 this->state_->set_value(val, false); 137 191 // TODO: schedule it to be set as ready when thread exits 138 192 } … … 140 194 void set_value_at_thread_exit(R&& val) 141 195 { 142 if (! state_)143 throw future_error{make_error_code(future_errc::no_state)}; 144 if ( state_->is_set())145 { 146 throw future_error{ 147 make_error_code(future_errc::promise_already_satisfied) 148 }; 149 } 150 151 state_->set_value(std::forward<R>(val), false);196 if (!this->state_) 197 throw future_error{make_error_code(future_errc::no_state)}; 198 if (this->state_->is_set()) 199 { 200 throw future_error{ 201 make_error_code(future_errc::promise_already_satisfied) 202 }; 203 } 204 205 this->state_->set_value(std::forward<R>(val), false); 152 206 // TODO: schedule it to be set as ready when thread exits 153 207 } 154 155 void set_exception_at_thread_exit(exception_ptr)156 {157 // TODO: No exception handling, no-op at this time.158 }159 160 private:161 void abandon_state_()162 {163 /**164 * Note: This is the 'abandon' move described in165 * 30.6.4 (7).166 * 1) If state is not ready:167 * a) Store exception of type future_error with168 * error condition broken_promise.169 * b) Mark state as ready.170 * 2) Rekease the state.171 */172 }173 174 aux::shared_state<R>* state_;175 208 }; 176 209 177 210 template<class R> 178 class promise<R&> 179 { 180 // TODO: Copy & modify once promise is done. 211 class promise<R&>: public aux::promise_base<R> 212 { // TODO: I'm afraid we will need aux::shared_state<R&> specialization for this :/ 213 public: 214 promise() 215 : aux::promise_base<R&>{} 216 { /* DUMMY BODY */ } 217 218 template<class Allocator> 219 promise(allocator_arg_t, const Allocator& a) 220 : aux::promise_base<R&>{} 221 { 222 // TODO: Use the allocator. 223 } 224 225 promise(promise&& rhs) noexcept 226 : aux::promise_base<R&>{move(rhs)} 227 { /* DUMMY BODY */ } 228 229 promise(const promise&) = delete; 230 231 ~promise() override = default; 232 233 promise& operator=(promise&& rhs) noexcept = default; 234 235 promise& operator=(const promise&) = delete; 181 236 }; 182 237 183 238 template<> 184 class promise<void> 185 { 186 // TODO: Copy & modify once promise is done. 239 class promise<void>: public aux::promise_base<void> 240 { 241 public: 242 promise() 243 : aux::promise_base<void>{} 244 { /* DUMMY BODY */ } 245 246 template<class Allocator> 247 promise(allocator_arg_t, const Allocator& a) 248 : aux::promise_base<void>{} 249 { 250 // TODO: Use the allocator. 251 } 252 253 promise(promise&& rhs) noexcept 254 : aux::promise_base<void>{move(rhs)} 255 { /* DUMMY BODY */ } 256 257 promise(const promise&) = delete; 258 259 ~promise() override = default; 260 261 promise& operator=(promise&& rhs) noexcept = default; 262 263 promise& operator=(const promise&) = delete; 264 265 void set_value() 266 { 267 if (!this->state_) 268 throw future_error{make_error_code(future_errc::no_state)}; 269 if (this->state_->is_set()) 270 { 271 throw future_error{ 272 make_error_code(future_errc::promise_already_satisfied) 273 }; 274 } 275 276 this->state_->set_value(); 277 } 187 278 }; 188 279
Note:
See TracChangeset
for help on using the changeset viewer.