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