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