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