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