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