1*4d6fc14bSjoerg //===------------------------- future.cpp ---------------------------------===// 2*4d6fc14bSjoerg // 3*4d6fc14bSjoerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*4d6fc14bSjoerg // See https://llvm.org/LICENSE.txt for license information. 5*4d6fc14bSjoerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*4d6fc14bSjoerg // 7*4d6fc14bSjoerg //===----------------------------------------------------------------------===// 8*4d6fc14bSjoerg 9*4d6fc14bSjoerg #include "__config" 10*4d6fc14bSjoerg 11*4d6fc14bSjoerg #ifndef _LIBCPP_HAS_NO_THREADS 12*4d6fc14bSjoerg 13*4d6fc14bSjoerg #include "future" 14*4d6fc14bSjoerg #include "string" 15*4d6fc14bSjoerg 16*4d6fc14bSjoerg _LIBCPP_BEGIN_NAMESPACE_STD 17*4d6fc14bSjoerg 18*4d6fc14bSjoerg class _LIBCPP_HIDDEN __future_error_category 19*4d6fc14bSjoerg : public __do_message 20*4d6fc14bSjoerg { 21*4d6fc14bSjoerg public: 22*4d6fc14bSjoerg virtual const char* name() const noexcept; 23*4d6fc14bSjoerg virtual string message(int ev) const; 24*4d6fc14bSjoerg }; 25*4d6fc14bSjoerg 26*4d6fc14bSjoerg const char* name() const27*4d6fc14bSjoerg__future_error_category::name() const noexcept 28*4d6fc14bSjoerg { 29*4d6fc14bSjoerg return "future"; 30*4d6fc14bSjoerg } 31*4d6fc14bSjoerg 32*4d6fc14bSjoerg #if defined(__clang__) 33*4d6fc14bSjoerg #pragma clang diagnostic push 34*4d6fc14bSjoerg #pragma clang diagnostic ignored "-Wswitch" 35*4d6fc14bSjoerg #elif defined(__GNUC__) || defined(__GNUG__) 36*4d6fc14bSjoerg #pragma GCC diagnostic push 37*4d6fc14bSjoerg #pragma GCC diagnostic ignored "-Wswitch" 38*4d6fc14bSjoerg #endif 39*4d6fc14bSjoerg 40*4d6fc14bSjoerg string message(int ev) const41*4d6fc14bSjoerg__future_error_category::message(int ev) const 42*4d6fc14bSjoerg { 43*4d6fc14bSjoerg switch (static_cast<future_errc>(ev)) 44*4d6fc14bSjoerg { 45*4d6fc14bSjoerg case future_errc(0): // For backwards compatibility with C++11 (LWG 2056) 46*4d6fc14bSjoerg case future_errc::broken_promise: 47*4d6fc14bSjoerg return string("The associated promise has been destructed prior " 48*4d6fc14bSjoerg "to the associated state becoming ready."); 49*4d6fc14bSjoerg case future_errc::future_already_retrieved: 50*4d6fc14bSjoerg return string("The future has already been retrieved from " 51*4d6fc14bSjoerg "the promise or packaged_task."); 52*4d6fc14bSjoerg case future_errc::promise_already_satisfied: 53*4d6fc14bSjoerg return string("The state of the promise has already been set."); 54*4d6fc14bSjoerg case future_errc::no_state: 55*4d6fc14bSjoerg return string("Operation not permitted on an object without " 56*4d6fc14bSjoerg "an associated state."); 57*4d6fc14bSjoerg } 58*4d6fc14bSjoerg return string("unspecified future_errc value\n"); 59*4d6fc14bSjoerg } 60*4d6fc14bSjoerg 61*4d6fc14bSjoerg #if defined(__clang__) 62*4d6fc14bSjoerg #pragma clang diagnostic pop 63*4d6fc14bSjoerg #elif defined(__GNUC__) || defined(__GNUG__) 64*4d6fc14bSjoerg #pragma GCC diagnostic pop 65*4d6fc14bSjoerg #endif 66*4d6fc14bSjoerg 67*4d6fc14bSjoerg const error_category& future_category()68*4d6fc14bSjoergfuture_category() noexcept 69*4d6fc14bSjoerg { 70*4d6fc14bSjoerg static __future_error_category __f; 71*4d6fc14bSjoerg return __f; 72*4d6fc14bSjoerg } 73*4d6fc14bSjoerg future_error(error_code __ec)74*4d6fc14bSjoergfuture_error::future_error(error_code __ec) 75*4d6fc14bSjoerg : logic_error(__ec.message()), 76*4d6fc14bSjoerg __ec_(__ec) 77*4d6fc14bSjoerg { 78*4d6fc14bSjoerg } 79*4d6fc14bSjoerg ~future_error()80*4d6fc14bSjoergfuture_error::~future_error() noexcept 81*4d6fc14bSjoerg { 82*4d6fc14bSjoerg } 83*4d6fc14bSjoerg 84*4d6fc14bSjoerg void __on_zero_shared()85*4d6fc14bSjoerg__assoc_sub_state::__on_zero_shared() noexcept 86*4d6fc14bSjoerg { 87*4d6fc14bSjoerg delete this; 88*4d6fc14bSjoerg } 89*4d6fc14bSjoerg 90*4d6fc14bSjoerg void set_value()91*4d6fc14bSjoerg__assoc_sub_state::set_value() 92*4d6fc14bSjoerg { 93*4d6fc14bSjoerg unique_lock<mutex> __lk(__mut_); 94*4d6fc14bSjoerg if (__has_value()) 95*4d6fc14bSjoerg __throw_future_error(future_errc::promise_already_satisfied); 96*4d6fc14bSjoerg __state_ |= __constructed | ready; 97*4d6fc14bSjoerg __cv_.notify_all(); 98*4d6fc14bSjoerg } 99*4d6fc14bSjoerg 100*4d6fc14bSjoerg void set_value_at_thread_exit()101*4d6fc14bSjoerg__assoc_sub_state::set_value_at_thread_exit() 102*4d6fc14bSjoerg { 103*4d6fc14bSjoerg unique_lock<mutex> __lk(__mut_); 104*4d6fc14bSjoerg if (__has_value()) 105*4d6fc14bSjoerg __throw_future_error(future_errc::promise_already_satisfied); 106*4d6fc14bSjoerg __state_ |= __constructed; 107*4d6fc14bSjoerg __thread_local_data()->__make_ready_at_thread_exit(this); 108*4d6fc14bSjoerg } 109*4d6fc14bSjoerg 110*4d6fc14bSjoerg void set_exception(exception_ptr __p)111*4d6fc14bSjoerg__assoc_sub_state::set_exception(exception_ptr __p) 112*4d6fc14bSjoerg { 113*4d6fc14bSjoerg unique_lock<mutex> __lk(__mut_); 114*4d6fc14bSjoerg if (__has_value()) 115*4d6fc14bSjoerg __throw_future_error(future_errc::promise_already_satisfied); 116*4d6fc14bSjoerg __exception_ = __p; 117*4d6fc14bSjoerg __state_ |= ready; 118*4d6fc14bSjoerg __cv_.notify_all(); 119*4d6fc14bSjoerg } 120*4d6fc14bSjoerg 121*4d6fc14bSjoerg void set_exception_at_thread_exit(exception_ptr __p)122*4d6fc14bSjoerg__assoc_sub_state::set_exception_at_thread_exit(exception_ptr __p) 123*4d6fc14bSjoerg { 124*4d6fc14bSjoerg unique_lock<mutex> __lk(__mut_); 125*4d6fc14bSjoerg if (__has_value()) 126*4d6fc14bSjoerg __throw_future_error(future_errc::promise_already_satisfied); 127*4d6fc14bSjoerg __exception_ = __p; 128*4d6fc14bSjoerg __thread_local_data()->__make_ready_at_thread_exit(this); 129*4d6fc14bSjoerg } 130*4d6fc14bSjoerg 131*4d6fc14bSjoerg void __make_ready()132*4d6fc14bSjoerg__assoc_sub_state::__make_ready() 133*4d6fc14bSjoerg { 134*4d6fc14bSjoerg unique_lock<mutex> __lk(__mut_); 135*4d6fc14bSjoerg __state_ |= ready; 136*4d6fc14bSjoerg __cv_.notify_all(); 137*4d6fc14bSjoerg } 138*4d6fc14bSjoerg 139*4d6fc14bSjoerg void copy()140*4d6fc14bSjoerg__assoc_sub_state::copy() 141*4d6fc14bSjoerg { 142*4d6fc14bSjoerg unique_lock<mutex> __lk(__mut_); 143*4d6fc14bSjoerg __sub_wait(__lk); 144*4d6fc14bSjoerg if (__exception_ != nullptr) 145*4d6fc14bSjoerg rethrow_exception(__exception_); 146*4d6fc14bSjoerg } 147*4d6fc14bSjoerg 148*4d6fc14bSjoerg void wait()149*4d6fc14bSjoerg__assoc_sub_state::wait() 150*4d6fc14bSjoerg { 151*4d6fc14bSjoerg unique_lock<mutex> __lk(__mut_); 152*4d6fc14bSjoerg __sub_wait(__lk); 153*4d6fc14bSjoerg } 154*4d6fc14bSjoerg 155*4d6fc14bSjoerg void __sub_wait(unique_lock<mutex> & __lk)156*4d6fc14bSjoerg__assoc_sub_state::__sub_wait(unique_lock<mutex>& __lk) 157*4d6fc14bSjoerg { 158*4d6fc14bSjoerg if (!__is_ready()) 159*4d6fc14bSjoerg { 160*4d6fc14bSjoerg if (__state_ & static_cast<unsigned>(deferred)) 161*4d6fc14bSjoerg { 162*4d6fc14bSjoerg __state_ &= ~static_cast<unsigned>(deferred); 163*4d6fc14bSjoerg __lk.unlock(); 164*4d6fc14bSjoerg __execute(); 165*4d6fc14bSjoerg } 166*4d6fc14bSjoerg else 167*4d6fc14bSjoerg while (!__is_ready()) 168*4d6fc14bSjoerg __cv_.wait(__lk); 169*4d6fc14bSjoerg } 170*4d6fc14bSjoerg } 171*4d6fc14bSjoerg 172*4d6fc14bSjoerg void __execute()173*4d6fc14bSjoerg__assoc_sub_state::__execute() 174*4d6fc14bSjoerg { 175*4d6fc14bSjoerg __throw_future_error(future_errc::no_state); 176*4d6fc14bSjoerg } 177*4d6fc14bSjoerg future(__assoc_sub_state * __state)178*4d6fc14bSjoergfuture<void>::future(__assoc_sub_state* __state) 179*4d6fc14bSjoerg : __state_(__state) 180*4d6fc14bSjoerg { 181*4d6fc14bSjoerg __state_->__attach_future(); 182*4d6fc14bSjoerg } 183*4d6fc14bSjoerg ~future()184*4d6fc14bSjoergfuture<void>::~future() 185*4d6fc14bSjoerg { 186*4d6fc14bSjoerg if (__state_) 187*4d6fc14bSjoerg __state_->__release_shared(); 188*4d6fc14bSjoerg } 189*4d6fc14bSjoerg 190*4d6fc14bSjoerg void get()191*4d6fc14bSjoergfuture<void>::get() 192*4d6fc14bSjoerg { 193*4d6fc14bSjoerg unique_ptr<__shared_count, __release_shared_count> __(__state_); 194*4d6fc14bSjoerg __assoc_sub_state* __s = __state_; 195*4d6fc14bSjoerg __state_ = nullptr; 196*4d6fc14bSjoerg __s->copy(); 197*4d6fc14bSjoerg } 198*4d6fc14bSjoerg promise()199*4d6fc14bSjoergpromise<void>::promise() 200*4d6fc14bSjoerg : __state_(new __assoc_sub_state) 201*4d6fc14bSjoerg { 202*4d6fc14bSjoerg } 203*4d6fc14bSjoerg ~promise()204*4d6fc14bSjoergpromise<void>::~promise() 205*4d6fc14bSjoerg { 206*4d6fc14bSjoerg if (__state_) 207*4d6fc14bSjoerg { 208*4d6fc14bSjoerg #ifndef _LIBCPP_NO_EXCEPTIONS 209*4d6fc14bSjoerg if (!__state_->__has_value() && __state_->use_count() > 1) 210*4d6fc14bSjoerg __state_->set_exception(make_exception_ptr( 211*4d6fc14bSjoerg future_error(make_error_code(future_errc::broken_promise)) 212*4d6fc14bSjoerg )); 213*4d6fc14bSjoerg #endif // _LIBCPP_NO_EXCEPTIONS 214*4d6fc14bSjoerg __state_->__release_shared(); 215*4d6fc14bSjoerg } 216*4d6fc14bSjoerg } 217*4d6fc14bSjoerg 218*4d6fc14bSjoerg future<void> get_future()219*4d6fc14bSjoergpromise<void>::get_future() 220*4d6fc14bSjoerg { 221*4d6fc14bSjoerg if (__state_ == nullptr) 222*4d6fc14bSjoerg __throw_future_error(future_errc::no_state); 223*4d6fc14bSjoerg return future<void>(__state_); 224*4d6fc14bSjoerg } 225*4d6fc14bSjoerg 226*4d6fc14bSjoerg void set_value()227*4d6fc14bSjoergpromise<void>::set_value() 228*4d6fc14bSjoerg { 229*4d6fc14bSjoerg if (__state_ == nullptr) 230*4d6fc14bSjoerg __throw_future_error(future_errc::no_state); 231*4d6fc14bSjoerg __state_->set_value(); 232*4d6fc14bSjoerg } 233*4d6fc14bSjoerg 234*4d6fc14bSjoerg void set_exception(exception_ptr __p)235*4d6fc14bSjoergpromise<void>::set_exception(exception_ptr __p) 236*4d6fc14bSjoerg { 237*4d6fc14bSjoerg if (__state_ == nullptr) 238*4d6fc14bSjoerg __throw_future_error(future_errc::no_state); 239*4d6fc14bSjoerg __state_->set_exception(__p); 240*4d6fc14bSjoerg } 241*4d6fc14bSjoerg 242*4d6fc14bSjoerg void set_value_at_thread_exit()243*4d6fc14bSjoergpromise<void>::set_value_at_thread_exit() 244*4d6fc14bSjoerg { 245*4d6fc14bSjoerg if (__state_ == nullptr) 246*4d6fc14bSjoerg __throw_future_error(future_errc::no_state); 247*4d6fc14bSjoerg __state_->set_value_at_thread_exit(); 248*4d6fc14bSjoerg } 249*4d6fc14bSjoerg 250*4d6fc14bSjoerg void set_exception_at_thread_exit(exception_ptr __p)251*4d6fc14bSjoergpromise<void>::set_exception_at_thread_exit(exception_ptr __p) 252*4d6fc14bSjoerg { 253*4d6fc14bSjoerg if (__state_ == nullptr) 254*4d6fc14bSjoerg __throw_future_error(future_errc::no_state); 255*4d6fc14bSjoerg __state_->set_exception_at_thread_exit(__p); 256*4d6fc14bSjoerg } 257*4d6fc14bSjoerg ~shared_future()258*4d6fc14bSjoergshared_future<void>::~shared_future() 259*4d6fc14bSjoerg { 260*4d6fc14bSjoerg if (__state_) 261*4d6fc14bSjoerg __state_->__release_shared(); 262*4d6fc14bSjoerg } 263*4d6fc14bSjoerg 264*4d6fc14bSjoerg shared_future<void>& operator =(const shared_future & __rhs)265*4d6fc14bSjoergshared_future<void>::operator=(const shared_future& __rhs) 266*4d6fc14bSjoerg { 267*4d6fc14bSjoerg if (__rhs.__state_) 268*4d6fc14bSjoerg __rhs.__state_->__add_shared(); 269*4d6fc14bSjoerg if (__state_) 270*4d6fc14bSjoerg __state_->__release_shared(); 271*4d6fc14bSjoerg __state_ = __rhs.__state_; 272*4d6fc14bSjoerg return *this; 273*4d6fc14bSjoerg } 274*4d6fc14bSjoerg 275*4d6fc14bSjoerg _LIBCPP_END_NAMESPACE_STD 276*4d6fc14bSjoerg 277*4d6fc14bSjoerg #endif // !_LIBCPP_HAS_NO_THREADS 278