1227825Stheraven//===------------------------- future.cpp ---------------------------------===//
2227825Stheraven//
3227825Stheraven//                     The LLVM Compiler Infrastructure
4227825Stheraven//
5227825Stheraven// This file is dual licensed under the MIT and the University of Illinois Open
6227825Stheraven// Source Licenses. See LICENSE.TXT for details.
7227825Stheraven//
8227825Stheraven//===----------------------------------------------------------------------===//
9227825Stheraven
10227825Stheraven#include "future"
11227825Stheraven#include "string"
12227825Stheraven
13227825Stheraven_LIBCPP_BEGIN_NAMESPACE_STD
14227825Stheraven
15227825Stheravenclass _LIBCPP_HIDDEN __future_error_category
16227825Stheraven    : public __do_message
17227825Stheraven{
18227825Stheravenpublic:
19227825Stheraven    virtual const char* name() const _NOEXCEPT;
20227825Stheraven    virtual string message(int ev) const;
21227825Stheraven};
22227825Stheraven
23227825Stheravenconst char*
24227825Stheraven__future_error_category::name() const _NOEXCEPT
25227825Stheraven{
26227825Stheraven    return "future";
27227825Stheraven}
28227825Stheraven
29227825Stheravenstring
30227825Stheraven__future_error_category::message(int ev) const
31227825Stheraven{
32232950Stheraven    switch (static_cast<future_errc>(ev))
33227825Stheraven    {
34227825Stheraven    case future_errc::broken_promise:
35227825Stheraven        return string("The associated promise has been destructed prior "
36227825Stheraven                      "to the associated state becoming ready.");
37227825Stheraven    case future_errc::future_already_retrieved:
38227825Stheraven        return string("The future has already been retrieved from "
39227825Stheraven                      "the promise or packaged_task.");
40227825Stheraven    case future_errc::promise_already_satisfied:
41227825Stheraven        return string("The state of the promise has already been set.");
42227825Stheraven    case future_errc::no_state:
43227825Stheraven        return string("Operation not permitted on an object without "
44227825Stheraven                      "an associated state.");
45227825Stheraven    }
46227825Stheraven    return string("unspecified future_errc value\n");
47227825Stheraven}
48227825Stheraven
49227825Stheravenconst error_category&
50241903Sdimfuture_category() _NOEXCEPT
51227825Stheraven{
52227825Stheraven    static __future_error_category __f;
53227825Stheraven    return __f;
54227825Stheraven}
55227825Stheraven
56227825Stheravenfuture_error::future_error(error_code __ec)
57227825Stheraven    : logic_error(__ec.message()),
58227825Stheraven      __ec_(__ec)
59227825Stheraven{
60227825Stheraven}
61227825Stheraven
62227825Stheravenfuture_error::~future_error() _NOEXCEPT
63227825Stheraven{
64227825Stheraven}
65227825Stheraven
66227825Stheravenvoid
67227825Stheraven__assoc_sub_state::__on_zero_shared() _NOEXCEPT
68227825Stheraven{
69227825Stheraven    delete this;
70227825Stheraven}
71227825Stheraven
72227825Stheravenvoid
73227825Stheraven__assoc_sub_state::set_value()
74227825Stheraven{
75227825Stheraven    unique_lock<mutex> __lk(__mut_);
76227825Stheraven#ifndef _LIBCPP_NO_EXCEPTIONS
77227825Stheraven    if (__has_value())
78227825Stheraven        throw future_error(make_error_code(future_errc::promise_already_satisfied));
79227825Stheraven#endif
80227825Stheraven    __state_ |= __constructed | ready;
81246487Stheraven    __cv_.notify_all();
82227825Stheraven    __lk.unlock();
83227825Stheraven}
84227825Stheraven
85227825Stheravenvoid
86227825Stheraven__assoc_sub_state::set_value_at_thread_exit()
87227825Stheraven{
88227825Stheraven    unique_lock<mutex> __lk(__mut_);
89227825Stheraven#ifndef _LIBCPP_NO_EXCEPTIONS
90227825Stheraven    if (__has_value())
91227825Stheraven        throw future_error(make_error_code(future_errc::promise_already_satisfied));
92227825Stheraven#endif
93227825Stheraven    __state_ |= __constructed;
94227825Stheraven    __thread_local_data()->__make_ready_at_thread_exit(this);
95227825Stheraven    __lk.unlock();
96227825Stheraven}
97227825Stheraven
98227825Stheravenvoid
99227825Stheraven__assoc_sub_state::set_exception(exception_ptr __p)
100227825Stheraven{
101227825Stheraven    unique_lock<mutex> __lk(__mut_);
102227825Stheraven#ifndef _LIBCPP_NO_EXCEPTIONS
103227825Stheraven    if (__has_value())
104227825Stheraven        throw future_error(make_error_code(future_errc::promise_already_satisfied));
105227825Stheraven#endif
106227825Stheraven    __exception_ = __p;
107227825Stheraven    __state_ |= ready;
108227825Stheraven    __lk.unlock();
109227825Stheraven    __cv_.notify_all();
110227825Stheraven}
111227825Stheraven
112227825Stheravenvoid
113227825Stheraven__assoc_sub_state::set_exception_at_thread_exit(exception_ptr __p)
114227825Stheraven{
115227825Stheraven    unique_lock<mutex> __lk(__mut_);
116227825Stheraven#ifndef _LIBCPP_NO_EXCEPTIONS
117227825Stheraven    if (__has_value())
118227825Stheraven        throw future_error(make_error_code(future_errc::promise_already_satisfied));
119227825Stheraven#endif
120227825Stheraven    __exception_ = __p;
121227825Stheraven    __thread_local_data()->__make_ready_at_thread_exit(this);
122227825Stheraven    __lk.unlock();
123227825Stheraven}
124227825Stheraven
125227825Stheravenvoid
126227825Stheraven__assoc_sub_state::__make_ready()
127227825Stheraven{
128227825Stheraven    unique_lock<mutex> __lk(__mut_);
129227825Stheraven    __state_ |= ready;
130227825Stheraven    __lk.unlock();
131227825Stheraven    __cv_.notify_all();
132227825Stheraven}
133227825Stheraven
134227825Stheravenvoid
135227825Stheraven__assoc_sub_state::copy()
136227825Stheraven{
137227825Stheraven    unique_lock<mutex> __lk(__mut_);
138227825Stheraven    __sub_wait(__lk);
139227825Stheraven    if (__exception_ != nullptr)
140227825Stheraven        rethrow_exception(__exception_);
141227825Stheraven}
142227825Stheraven
143227825Stheravenvoid
144227825Stheraven__assoc_sub_state::wait()
145227825Stheraven{
146227825Stheraven    unique_lock<mutex> __lk(__mut_);
147227825Stheraven    __sub_wait(__lk);
148227825Stheraven}
149227825Stheraven
150227825Stheravenvoid
151227825Stheraven__assoc_sub_state::__sub_wait(unique_lock<mutex>& __lk)
152227825Stheraven{
153227825Stheraven    if (!__is_ready())
154227825Stheraven    {
155232950Stheraven        if (__state_ & static_cast<unsigned>(deferred))
156227825Stheraven        {
157232950Stheraven            __state_ &= ~static_cast<unsigned>(deferred);
158227825Stheraven            __lk.unlock();
159227825Stheraven            __execute();
160227825Stheraven        }
161227825Stheraven        else
162227825Stheraven            while (!__is_ready())
163227825Stheraven                __cv_.wait(__lk);
164227825Stheraven    }
165227825Stheraven}
166227825Stheraven
167227825Stheravenvoid
168227825Stheraven__assoc_sub_state::__execute()
169227825Stheraven{
170227825Stheraven#ifndef _LIBCPP_NO_EXCEPTIONS
171227825Stheraven    throw future_error(make_error_code(future_errc::no_state));
172227825Stheraven#endif
173227825Stheraven}
174227825Stheraven
175227825Stheravenfuture<void>::future(__assoc_sub_state* __state)
176227825Stheraven    : __state_(__state)
177227825Stheraven{
178227825Stheraven#ifndef _LIBCPP_NO_EXCEPTIONS
179227825Stheraven    if (__state_->__has_future_attached())
180227825Stheraven        throw future_error(make_error_code(future_errc::future_already_retrieved));
181227825Stheraven#endif
182227825Stheraven    __state_->__add_shared();
183227825Stheraven    __state_->__set_future_attached();
184227825Stheraven}
185227825Stheraven
186227825Stheravenfuture<void>::~future()
187227825Stheraven{
188227825Stheraven    if (__state_)
189227825Stheraven        __state_->__release_shared();
190227825Stheraven}
191227825Stheraven
192227825Stheravenvoid
193227825Stheravenfuture<void>::get()
194227825Stheraven{
195227825Stheraven    unique_ptr<__shared_count, __release_shared_count> __(__state_);
196227825Stheraven    __assoc_sub_state* __s = __state_;
197227825Stheraven    __state_ = nullptr;
198227825Stheraven    __s->copy();
199227825Stheraven}
200227825Stheraven
201227825Stheravenpromise<void>::promise()
202227825Stheraven    : __state_(new __assoc_sub_state)
203227825Stheraven{
204227825Stheraven}
205227825Stheraven
206227825Stheravenpromise<void>::~promise()
207227825Stheraven{
208227825Stheraven    if (__state_)
209227825Stheraven    {
210227825Stheraven        if (!__state_->__has_value() && __state_->use_count() > 1)
211227825Stheraven            __state_->set_exception(make_exception_ptr(
212227825Stheraven                      future_error(make_error_code(future_errc::broken_promise))
213227825Stheraven                                                      ));
214227825Stheraven        __state_->__release_shared();
215227825Stheraven    }
216227825Stheraven}
217227825Stheraven
218227825Stheravenfuture<void>
219227825Stheravenpromise<void>::get_future()
220227825Stheraven{
221227825Stheraven#ifndef _LIBCPP_NO_EXCEPTIONS
222227825Stheraven    if (__state_ == nullptr)
223227825Stheraven        throw future_error(make_error_code(future_errc::no_state));
224227825Stheraven#endif
225227825Stheraven    return future<void>(__state_);
226227825Stheraven}
227227825Stheraven
228227825Stheravenvoid
229227825Stheravenpromise<void>::set_value()
230227825Stheraven{
231227825Stheraven#ifndef _LIBCPP_NO_EXCEPTIONS
232227825Stheraven    if (__state_ == nullptr)
233227825Stheraven        throw future_error(make_error_code(future_errc::no_state));
234227825Stheraven#endif
235227825Stheraven    __state_->set_value();
236227825Stheraven}
237227825Stheraven
238227825Stheravenvoid
239227825Stheravenpromise<void>::set_exception(exception_ptr __p)
240227825Stheraven{
241227825Stheraven#ifndef _LIBCPP_NO_EXCEPTIONS
242227825Stheraven    if (__state_ == nullptr)
243227825Stheraven        throw future_error(make_error_code(future_errc::no_state));
244227825Stheraven#endif
245227825Stheraven    __state_->set_exception(__p);
246227825Stheraven}
247227825Stheraven
248227825Stheravenvoid
249227825Stheravenpromise<void>::set_value_at_thread_exit()
250227825Stheraven{
251227825Stheraven#ifndef _LIBCPP_NO_EXCEPTIONS
252227825Stheraven    if (__state_ == nullptr)
253227825Stheraven        throw future_error(make_error_code(future_errc::no_state));
254227825Stheraven#endif
255227825Stheraven    __state_->set_value_at_thread_exit();
256227825Stheraven}
257227825Stheraven
258227825Stheravenvoid
259227825Stheravenpromise<void>::set_exception_at_thread_exit(exception_ptr __p)
260227825Stheraven{
261227825Stheraven#ifndef _LIBCPP_NO_EXCEPTIONS
262227825Stheraven    if (__state_ == nullptr)
263227825Stheraven        throw future_error(make_error_code(future_errc::no_state));
264227825Stheraven#endif
265227825Stheraven    __state_->set_exception_at_thread_exit(__p);
266227825Stheraven}
267227825Stheraven
268227825Stheravenshared_future<void>::~shared_future()
269227825Stheraven{
270227825Stheraven    if (__state_)
271227825Stheraven        __state_->__release_shared();
272227825Stheraven}
273227825Stheraven
274227825Stheravenshared_future<void>&
275227825Stheravenshared_future<void>::operator=(const shared_future& __rhs)
276227825Stheraven{
277227825Stheraven    if (__rhs.__state_)
278227825Stheraven        __rhs.__state_->__add_shared();
279227825Stheraven    if (__state_)
280227825Stheraven        __state_->__release_shared();
281227825Stheraven    __state_ = __rhs.__state_;
282227825Stheraven    return *this;
283227825Stheraven}
284227825Stheraven
285227825Stheraven_LIBCPP_END_NAMESPACE_STD
286