source: mainline/uspace/lib/cpp/include/__bits/thread/future.hpp@ a95e75e

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since a95e75e was a95e75e, checked in by Jaroslav Jindrak <dzejrou@…>, 6 years ago

cpp: split future.hpp into subheaders for each type

  • Property mode set to 100644
File size: 6.3 KB
Line 
1/*
2 * Copyright (c) 2019 Jaroslav Jindrak
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#ifndef LIBCPP_BITS_THREAD_FUTURE
30#define LIBCPP_BITS_THREAD_FUTURE
31
32#include <cassert>
33#include <memory>
34#include <system_error>
35#include <thread>
36#include <tuple>
37#include <type_traits>
38#include <utility>
39
40namespace std
41{
42 /**
43 * 30.6, futures:
44 */
45
46 enum class future_errc
47 { // The 5001 start is to not collide with system_error's codes.
48 broken_promise = 5001,
49 future_already_retrieved,
50 promise_already_satisfied,
51 no_state
52 };
53
54 enum class future_status
55 {
56 ready,
57 timeout,
58 deferred
59 };
60
61 /**
62 * 30.6.2, error handling:
63 */
64
65 template<>
66 struct is_error_code_enum<future_errc>: true_type
67 { /* DUMMY BODY */ };
68
69 error_code make_error_code(future_errc) noexcept;
70 error_condition make_error_condition(future_errc) noexcept;
71
72 const error_category& future_category() noexcept;
73
74 /**
75 * 30.6.3, class future_error:
76 */
77
78 class future_error: public logic_error
79 {
80 public:
81 future_error(error_code ec);
82
83 const error_code& code() const noexcept;
84 const char* what() const noexcept;
85
86 private:
87 error_code code_;
88 };
89
90 /**
91 * 30.6.6, class template future:
92 */
93
94 template<class R>
95 class shared_future;
96
97 template<class R>
98 class future
99 {
100 public:
101 future() noexcept
102 : state_{nullptr}
103 { /* DUMMY BODY */ }
104
105 future(const future&) = delete;
106
107 future(future&& rhs) noexcept
108 : state_{std::move(rhs.state_)}
109 {
110 rhs.state_ = nullptr;
111 }
112
113 future(aux::shared_state<R>* state)
114 : state_{state}
115 {
116 /**
117 * Note: This is a custom non-standard constructor that allows
118 * us to create a future directly from a shared state. This
119 * should never be a problem as aux::shared_state is a private
120 * type and future has no constructor templates.
121 */
122 }
123
124 ~future()
125 {
126 release_state_();
127 }
128
129 future& operator=(const future) = delete;
130
131 future& operator=(future&& rhs) noexcept
132 {
133 release_state_();
134 state_ = std::move(rhs.state_);
135 rhs.state_ = nullptr;
136 }
137
138 shared_future<R> share()
139 {
140 return shared_future<R>(std::move(*this));
141 }
142
143 R get()
144 {
145 assert(state_);
146
147 wait();
148
149 if (state_->has_exception())
150 state_->throw_stored_exception();
151 auto res = std::move(state_->get());
152
153 release_state_();
154
155 return res;
156 }
157
158 bool valid() const noexcept
159 {
160 return state_ != nullptr;
161 }
162
163 void wait() const noexcept
164 {
165 assert(state_);
166
167 state_->wait();
168 }
169
170 template<class Rep, class Period>
171 future_status wait_for(const chrono::duration<Rep, Period>& rel_time) const
172 {
173 assert(state_);
174
175 return state_->wait_for(rel_time);
176 }
177
178 template<class Clock, class Duration>
179 future_status wait_until(const chrono::time_point<Clock, Duration>& abs_time) const
180 {
181 assert(state_);
182
183 return state_->wait_until(abs_time);
184 }
185
186 private:
187 void release_state_()
188 {
189 if (!state_)
190 return;
191
192 /**
193 * Note: This is the 'release' move described in
194 * 30.6.4 (5).
195 * Last reference to state -> destroy state.
196 * Decrement refcount of state otherwise.
197 * Will not block, unless all following hold:
198 * 1) State was created by call to std::async.
199 * 2) State is not yet ready.
200 * 3) This was the last reference to the shared state.
201 */
202 if (state_->decrement())
203 {
204 /**
205 * The destroy call handles the special case
206 * when 1) - 3) hold.
207 */
208 state_->destroy();
209 delete state_;
210 state_ = nullptr;
211 }
212 }
213
214 aux::shared_state<R>* state_;
215 };
216
217 template<class R>
218 class future<R&>
219 {
220 // TODO: Copy & modify once future is done.
221 };
222
223 template<>
224 class future<void>
225 {
226 // TODO: Copy & modify once future is done.
227 };
228}
229
230#endif
Note: See TracBrowser for help on using the repository browser.