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