14684ddb6SLionel Sambuc //===------------------------- future.cpp ---------------------------------===// 24684ddb6SLionel Sambuc // 34684ddb6SLionel Sambuc // The LLVM Compiler Infrastructure 44684ddb6SLionel Sambuc // 54684ddb6SLionel Sambuc // This file is dual licensed under the MIT and the University of Illinois Open 64684ddb6SLionel Sambuc // Source Licenses. See LICENSE.TXT for details. 74684ddb6SLionel Sambuc // 84684ddb6SLionel Sambuc //===----------------------------------------------------------------------===// 94684ddb6SLionel Sambuc 10*0a6a1f1dSLionel Sambuc #include "__config" 11*0a6a1f1dSLionel Sambuc 12*0a6a1f1dSLionel Sambuc #ifndef _LIBCPP_HAS_NO_THREADS 13*0a6a1f1dSLionel Sambuc 144684ddb6SLionel Sambuc #include "future" 154684ddb6SLionel Sambuc #include "string" 164684ddb6SLionel Sambuc 174684ddb6SLionel Sambuc _LIBCPP_BEGIN_NAMESPACE_STD 184684ddb6SLionel Sambuc 194684ddb6SLionel Sambuc class _LIBCPP_HIDDEN __future_error_category 204684ddb6SLionel Sambuc : public __do_message 214684ddb6SLionel Sambuc { 224684ddb6SLionel Sambuc public: 234684ddb6SLionel Sambuc virtual const char* name() const _NOEXCEPT; 244684ddb6SLionel Sambuc virtual string message(int ev) const; 254684ddb6SLionel Sambuc }; 264684ddb6SLionel Sambuc 274684ddb6SLionel Sambuc const char* name() const284684ddb6SLionel Sambuc__future_error_category::name() const _NOEXCEPT 294684ddb6SLionel Sambuc { 304684ddb6SLionel Sambuc return "future"; 314684ddb6SLionel Sambuc } 324684ddb6SLionel Sambuc 33*0a6a1f1dSLionel Sambuc #if defined(__clang__) 344684ddb6SLionel Sambuc #pragma clang diagnostic push 354684ddb6SLionel Sambuc #pragma clang diagnostic ignored "-Wswitch" 36*0a6a1f1dSLionel Sambuc #elif defined(__GNUC__) || defined(__GNUG__) 37*0a6a1f1dSLionel Sambuc #pragma GCC diagnostic push 38*0a6a1f1dSLionel Sambuc #pragma GCC diagnostic ignored "-Wswitch" 39*0a6a1f1dSLionel Sambuc #endif 404684ddb6SLionel Sambuc 414684ddb6SLionel Sambuc string message(int ev) const424684ddb6SLionel Sambuc__future_error_category::message(int ev) const 434684ddb6SLionel Sambuc { 444684ddb6SLionel Sambuc switch (static_cast<future_errc>(ev)) 454684ddb6SLionel Sambuc { 464684ddb6SLionel Sambuc case future_errc(0): // For backwards compatibility with C++11 (LWG 2056) 474684ddb6SLionel Sambuc case future_errc::broken_promise: 484684ddb6SLionel Sambuc return string("The associated promise has been destructed prior " 494684ddb6SLionel Sambuc "to the associated state becoming ready."); 504684ddb6SLionel Sambuc case future_errc::future_already_retrieved: 514684ddb6SLionel Sambuc return string("The future has already been retrieved from " 524684ddb6SLionel Sambuc "the promise or packaged_task."); 534684ddb6SLionel Sambuc case future_errc::promise_already_satisfied: 544684ddb6SLionel Sambuc return string("The state of the promise has already been set."); 554684ddb6SLionel Sambuc case future_errc::no_state: 564684ddb6SLionel Sambuc return string("Operation not permitted on an object without " 574684ddb6SLionel Sambuc "an associated state."); 584684ddb6SLionel Sambuc } 594684ddb6SLionel Sambuc return string("unspecified future_errc value\n"); 604684ddb6SLionel Sambuc } 614684ddb6SLionel Sambuc 62*0a6a1f1dSLionel Sambuc #if defined(__clang__) 634684ddb6SLionel Sambuc #pragma clang diagnostic pop 64*0a6a1f1dSLionel Sambuc #elif defined(__GNUC__) || defined(__GNUG__) 65*0a6a1f1dSLionel Sambuc #pragma GCC diagnostic pop 66*0a6a1f1dSLionel Sambuc #endif 674684ddb6SLionel Sambuc 684684ddb6SLionel Sambuc const error_category& future_category()694684ddb6SLionel Sambucfuture_category() _NOEXCEPT 704684ddb6SLionel Sambuc { 714684ddb6SLionel Sambuc static __future_error_category __f; 724684ddb6SLionel Sambuc return __f; 734684ddb6SLionel Sambuc } 744684ddb6SLionel Sambuc future_error(error_code __ec)754684ddb6SLionel Sambucfuture_error::future_error(error_code __ec) 764684ddb6SLionel Sambuc : logic_error(__ec.message()), 774684ddb6SLionel Sambuc __ec_(__ec) 784684ddb6SLionel Sambuc { 794684ddb6SLionel Sambuc } 804684ddb6SLionel Sambuc ~future_error()814684ddb6SLionel Sambucfuture_error::~future_error() _NOEXCEPT 824684ddb6SLionel Sambuc { 834684ddb6SLionel Sambuc } 844684ddb6SLionel Sambuc 854684ddb6SLionel Sambuc void __on_zero_shared()864684ddb6SLionel Sambuc__assoc_sub_state::__on_zero_shared() _NOEXCEPT 874684ddb6SLionel Sambuc { 884684ddb6SLionel Sambuc delete this; 894684ddb6SLionel Sambuc } 904684ddb6SLionel Sambuc 914684ddb6SLionel Sambuc void set_value()924684ddb6SLionel Sambuc__assoc_sub_state::set_value() 934684ddb6SLionel Sambuc { 944684ddb6SLionel Sambuc unique_lock<mutex> __lk(__mut_); 954684ddb6SLionel Sambuc #ifndef _LIBCPP_NO_EXCEPTIONS 964684ddb6SLionel Sambuc if (__has_value()) 974684ddb6SLionel Sambuc throw future_error(make_error_code(future_errc::promise_already_satisfied)); 984684ddb6SLionel Sambuc #endif 994684ddb6SLionel Sambuc __state_ |= __constructed | ready; 1004684ddb6SLionel Sambuc __cv_.notify_all(); 1014684ddb6SLionel Sambuc } 1024684ddb6SLionel Sambuc 1034684ddb6SLionel Sambuc void set_value_at_thread_exit()1044684ddb6SLionel Sambuc__assoc_sub_state::set_value_at_thread_exit() 1054684ddb6SLionel Sambuc { 1064684ddb6SLionel Sambuc unique_lock<mutex> __lk(__mut_); 1074684ddb6SLionel Sambuc #ifndef _LIBCPP_NO_EXCEPTIONS 1084684ddb6SLionel Sambuc if (__has_value()) 1094684ddb6SLionel Sambuc throw future_error(make_error_code(future_errc::promise_already_satisfied)); 1104684ddb6SLionel Sambuc #endif 1114684ddb6SLionel Sambuc __state_ |= __constructed; 1124684ddb6SLionel Sambuc __thread_local_data()->__make_ready_at_thread_exit(this); 1134684ddb6SLionel Sambuc } 1144684ddb6SLionel Sambuc 1154684ddb6SLionel Sambuc void set_exception(exception_ptr __p)1164684ddb6SLionel Sambuc__assoc_sub_state::set_exception(exception_ptr __p) 1174684ddb6SLionel Sambuc { 1184684ddb6SLionel Sambuc unique_lock<mutex> __lk(__mut_); 1194684ddb6SLionel Sambuc #ifndef _LIBCPP_NO_EXCEPTIONS 1204684ddb6SLionel Sambuc if (__has_value()) 1214684ddb6SLionel Sambuc throw future_error(make_error_code(future_errc::promise_already_satisfied)); 1224684ddb6SLionel Sambuc #endif 1234684ddb6SLionel Sambuc __exception_ = __p; 1244684ddb6SLionel Sambuc __state_ |= ready; 1254684ddb6SLionel Sambuc __cv_.notify_all(); 1264684ddb6SLionel Sambuc } 1274684ddb6SLionel Sambuc 1284684ddb6SLionel Sambuc void set_exception_at_thread_exit(exception_ptr __p)1294684ddb6SLionel Sambuc__assoc_sub_state::set_exception_at_thread_exit(exception_ptr __p) 1304684ddb6SLionel Sambuc { 1314684ddb6SLionel Sambuc unique_lock<mutex> __lk(__mut_); 1324684ddb6SLionel Sambuc #ifndef _LIBCPP_NO_EXCEPTIONS 1334684ddb6SLionel Sambuc if (__has_value()) 1344684ddb6SLionel Sambuc throw future_error(make_error_code(future_errc::promise_already_satisfied)); 1354684ddb6SLionel Sambuc #endif 1364684ddb6SLionel Sambuc __exception_ = __p; 1374684ddb6SLionel Sambuc __thread_local_data()->__make_ready_at_thread_exit(this); 1384684ddb6SLionel Sambuc } 1394684ddb6SLionel Sambuc 1404684ddb6SLionel Sambuc void __make_ready()1414684ddb6SLionel Sambuc__assoc_sub_state::__make_ready() 1424684ddb6SLionel Sambuc { 1434684ddb6SLionel Sambuc unique_lock<mutex> __lk(__mut_); 1444684ddb6SLionel Sambuc __state_ |= ready; 1454684ddb6SLionel Sambuc __cv_.notify_all(); 1464684ddb6SLionel Sambuc } 1474684ddb6SLionel Sambuc 1484684ddb6SLionel Sambuc void copy()1494684ddb6SLionel Sambuc__assoc_sub_state::copy() 1504684ddb6SLionel Sambuc { 1514684ddb6SLionel Sambuc unique_lock<mutex> __lk(__mut_); 1524684ddb6SLionel Sambuc __sub_wait(__lk); 1534684ddb6SLionel Sambuc if (__exception_ != nullptr) 1544684ddb6SLionel Sambuc rethrow_exception(__exception_); 1554684ddb6SLionel Sambuc } 1564684ddb6SLionel Sambuc 1574684ddb6SLionel Sambuc void wait()1584684ddb6SLionel Sambuc__assoc_sub_state::wait() 1594684ddb6SLionel Sambuc { 1604684ddb6SLionel Sambuc unique_lock<mutex> __lk(__mut_); 1614684ddb6SLionel Sambuc __sub_wait(__lk); 1624684ddb6SLionel Sambuc } 1634684ddb6SLionel Sambuc 1644684ddb6SLionel Sambuc void __sub_wait(unique_lock<mutex> & __lk)1654684ddb6SLionel Sambuc__assoc_sub_state::__sub_wait(unique_lock<mutex>& __lk) 1664684ddb6SLionel Sambuc { 1674684ddb6SLionel Sambuc if (!__is_ready()) 1684684ddb6SLionel Sambuc { 1694684ddb6SLionel Sambuc if (__state_ & static_cast<unsigned>(deferred)) 1704684ddb6SLionel Sambuc { 1714684ddb6SLionel Sambuc __state_ &= ~static_cast<unsigned>(deferred); 1724684ddb6SLionel Sambuc __lk.unlock(); 1734684ddb6SLionel Sambuc __execute(); 1744684ddb6SLionel Sambuc } 1754684ddb6SLionel Sambuc else 1764684ddb6SLionel Sambuc while (!__is_ready()) 1774684ddb6SLionel Sambuc __cv_.wait(__lk); 1784684ddb6SLionel Sambuc } 1794684ddb6SLionel Sambuc } 1804684ddb6SLionel Sambuc 1814684ddb6SLionel Sambuc void __execute()1824684ddb6SLionel Sambuc__assoc_sub_state::__execute() 1834684ddb6SLionel Sambuc { 1844684ddb6SLionel Sambuc #ifndef _LIBCPP_NO_EXCEPTIONS 1854684ddb6SLionel Sambuc throw future_error(make_error_code(future_errc::no_state)); 1864684ddb6SLionel Sambuc #endif 1874684ddb6SLionel Sambuc } 1884684ddb6SLionel Sambuc future(__assoc_sub_state * __state)1894684ddb6SLionel Sambucfuture<void>::future(__assoc_sub_state* __state) 1904684ddb6SLionel Sambuc : __state_(__state) 1914684ddb6SLionel Sambuc { 1924684ddb6SLionel Sambuc #ifndef _LIBCPP_NO_EXCEPTIONS 1934684ddb6SLionel Sambuc if (__state_->__has_future_attached()) 1944684ddb6SLionel Sambuc throw future_error(make_error_code(future_errc::future_already_retrieved)); 1954684ddb6SLionel Sambuc #endif 1964684ddb6SLionel Sambuc __state_->__add_shared(); 1974684ddb6SLionel Sambuc __state_->__set_future_attached(); 1984684ddb6SLionel Sambuc } 1994684ddb6SLionel Sambuc ~future()2004684ddb6SLionel Sambucfuture<void>::~future() 2014684ddb6SLionel Sambuc { 2024684ddb6SLionel Sambuc if (__state_) 2034684ddb6SLionel Sambuc __state_->__release_shared(); 2044684ddb6SLionel Sambuc } 2054684ddb6SLionel Sambuc 2064684ddb6SLionel Sambuc void get()2074684ddb6SLionel Sambucfuture<void>::get() 2084684ddb6SLionel Sambuc { 2094684ddb6SLionel Sambuc unique_ptr<__shared_count, __release_shared_count> __(__state_); 2104684ddb6SLionel Sambuc __assoc_sub_state* __s = __state_; 2114684ddb6SLionel Sambuc __state_ = nullptr; 2124684ddb6SLionel Sambuc __s->copy(); 2134684ddb6SLionel Sambuc } 2144684ddb6SLionel Sambuc promise()2154684ddb6SLionel Sambucpromise<void>::promise() 2164684ddb6SLionel Sambuc : __state_(new __assoc_sub_state) 2174684ddb6SLionel Sambuc { 2184684ddb6SLionel Sambuc } 2194684ddb6SLionel Sambuc ~promise()2204684ddb6SLionel Sambucpromise<void>::~promise() 2214684ddb6SLionel Sambuc { 2224684ddb6SLionel Sambuc if (__state_) 2234684ddb6SLionel Sambuc { 2244684ddb6SLionel Sambuc if (!__state_->__has_value() && __state_->use_count() > 1) 2254684ddb6SLionel Sambuc __state_->set_exception(make_exception_ptr( 2264684ddb6SLionel Sambuc future_error(make_error_code(future_errc::broken_promise)) 2274684ddb6SLionel Sambuc )); 2284684ddb6SLionel Sambuc __state_->__release_shared(); 2294684ddb6SLionel Sambuc } 2304684ddb6SLionel Sambuc } 2314684ddb6SLionel Sambuc 2324684ddb6SLionel Sambuc future<void> get_future()2334684ddb6SLionel Sambucpromise<void>::get_future() 2344684ddb6SLionel Sambuc { 2354684ddb6SLionel Sambuc #ifndef _LIBCPP_NO_EXCEPTIONS 2364684ddb6SLionel Sambuc if (__state_ == nullptr) 2374684ddb6SLionel Sambuc throw future_error(make_error_code(future_errc::no_state)); 2384684ddb6SLionel Sambuc #endif 2394684ddb6SLionel Sambuc return future<void>(__state_); 2404684ddb6SLionel Sambuc } 2414684ddb6SLionel Sambuc 2424684ddb6SLionel Sambuc void set_value()2434684ddb6SLionel Sambucpromise<void>::set_value() 2444684ddb6SLionel Sambuc { 2454684ddb6SLionel Sambuc #ifndef _LIBCPP_NO_EXCEPTIONS 2464684ddb6SLionel Sambuc if (__state_ == nullptr) 2474684ddb6SLionel Sambuc throw future_error(make_error_code(future_errc::no_state)); 2484684ddb6SLionel Sambuc #endif 2494684ddb6SLionel Sambuc __state_->set_value(); 2504684ddb6SLionel Sambuc } 2514684ddb6SLionel Sambuc 2524684ddb6SLionel Sambuc void set_exception(exception_ptr __p)2534684ddb6SLionel Sambucpromise<void>::set_exception(exception_ptr __p) 2544684ddb6SLionel Sambuc { 2554684ddb6SLionel Sambuc #ifndef _LIBCPP_NO_EXCEPTIONS 2564684ddb6SLionel Sambuc if (__state_ == nullptr) 2574684ddb6SLionel Sambuc throw future_error(make_error_code(future_errc::no_state)); 2584684ddb6SLionel Sambuc #endif 2594684ddb6SLionel Sambuc __state_->set_exception(__p); 2604684ddb6SLionel Sambuc } 2614684ddb6SLionel Sambuc 2624684ddb6SLionel Sambuc void set_value_at_thread_exit()2634684ddb6SLionel Sambucpromise<void>::set_value_at_thread_exit() 2644684ddb6SLionel Sambuc { 2654684ddb6SLionel Sambuc #ifndef _LIBCPP_NO_EXCEPTIONS 2664684ddb6SLionel Sambuc if (__state_ == nullptr) 2674684ddb6SLionel Sambuc throw future_error(make_error_code(future_errc::no_state)); 2684684ddb6SLionel Sambuc #endif 2694684ddb6SLionel Sambuc __state_->set_value_at_thread_exit(); 2704684ddb6SLionel Sambuc } 2714684ddb6SLionel Sambuc 2724684ddb6SLionel Sambuc void set_exception_at_thread_exit(exception_ptr __p)2734684ddb6SLionel Sambucpromise<void>::set_exception_at_thread_exit(exception_ptr __p) 2744684ddb6SLionel Sambuc { 2754684ddb6SLionel Sambuc #ifndef _LIBCPP_NO_EXCEPTIONS 2764684ddb6SLionel Sambuc if (__state_ == nullptr) 2774684ddb6SLionel Sambuc throw future_error(make_error_code(future_errc::no_state)); 2784684ddb6SLionel Sambuc #endif 2794684ddb6SLionel Sambuc __state_->set_exception_at_thread_exit(__p); 2804684ddb6SLionel Sambuc } 2814684ddb6SLionel Sambuc ~shared_future()2824684ddb6SLionel Sambucshared_future<void>::~shared_future() 2834684ddb6SLionel Sambuc { 2844684ddb6SLionel Sambuc if (__state_) 2854684ddb6SLionel Sambuc __state_->__release_shared(); 2864684ddb6SLionel Sambuc } 2874684ddb6SLionel Sambuc 2884684ddb6SLionel Sambuc shared_future<void>& operator =(const shared_future & __rhs)2894684ddb6SLionel Sambucshared_future<void>::operator=(const shared_future& __rhs) 2904684ddb6SLionel Sambuc { 2914684ddb6SLionel Sambuc if (__rhs.__state_) 2924684ddb6SLionel Sambuc __rhs.__state_->__add_shared(); 2934684ddb6SLionel Sambuc if (__state_) 2944684ddb6SLionel Sambuc __state_->__release_shared(); 2954684ddb6SLionel Sambuc __state_ = __rhs.__state_; 2964684ddb6SLionel Sambuc return *this; 2974684ddb6SLionel Sambuc } 2984684ddb6SLionel Sambuc 2994684ddb6SLionel Sambuc _LIBCPP_END_NAMESPACE_STD 300*0a6a1f1dSLionel Sambuc 301*0a6a1f1dSLionel Sambuc #endif // !_LIBCPP_HAS_NO_THREADS 302