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

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

cpp: implemented promise and future for references

  • Property mode set to 100644
File size: 8.2 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 <__bits/thread/future_common.hpp>
33#include <__bits/thread/shared_state.hpp>
34#include <__bits/utility/forward_move.hpp>
35#include <cassert>
36
37namespace std
38{
39 /**
40 * 30.6.6, class template future:
41 */
42
43 namespace aux
44 {
45 template<class R>
46 class future_base
47 {
48 public:
49 future_base() noexcept
50 : state_{nullptr}
51 { /* DUMMY BODY */ }
52
53 future_base(const future_base&) = delete;
54
55 future_base(future_base&& rhs) noexcept
56 : state_{move(rhs.state_)}
57 {
58 rhs.state_ = nullptr;
59 }
60
61 future_base(aux::shared_state<R>* state)
62 : state_{state}
63 {
64 /**
65 * Note: This is a custom non-standard constructor that allows
66 * us to create a future directly from a shared state. This
67 * should never be a problem as aux::shared_state is a private
68 * type and future has no constructor templates.
69 */
70 }
71
72 virtual ~future_base()
73 {
74 release_state_();
75 }
76
77 future_base& operator=(const future_base&) = delete;
78
79 future_base& operator=(future_base&& rhs) noexcept
80 {
81 release_state_();
82 state_ = move(rhs.state_);
83 rhs.state_ = nullptr;
84 }
85
86 bool valid() const noexcept
87 {
88 return state_ != nullptr;
89 }
90
91 void wait() const noexcept
92 {
93 assert(state_);
94
95 state_->wait();
96 }
97
98 template<class Rep, class Period>
99 future_status
100 wait_for(const chrono::duration<Rep, Period>& rel_time) const
101 {
102 assert(state_);
103
104 return state_->wait_for(rel_time);
105 }
106
107 template<class Clock, class Duration>
108 future_status
109 wait_until(
110 const chrono::time_point<Clock, Duration>& abs_time
111 ) const
112 {
113 assert(state_);
114
115 return state_->wait_until(abs_time);
116 }
117
118 protected:
119 void release_state_()
120 {
121 if (!state_)
122 return;
123
124 /**
125 * Note: This is the 'release' move described in
126 * 30.6.4 (5).
127 * Last reference to state -> destroy state.
128 * Decrement refcount of state otherwise.
129 * Will not block, unless all following hold:
130 * 1) State was created by call to std::async.
131 * 2) State is not yet ready.
132 * 3) This was the last reference to the shared state.
133 */
134 if (state_->decrement())
135 {
136 /**
137 * The destroy call handles the special case
138 * when 1) - 3) hold.
139 */
140 state_->destroy();
141 delete state_;
142 state_ = nullptr;
143 }
144 }
145
146 aux::shared_state<R>* state_;
147 };
148 }
149
150 template<class R>
151 class shared_future;
152
153 template<class R>
154 class future: public aux::future_base<R>
155 {
156 public:
157 future() noexcept
158 : aux::future_base<R>{}
159 { /* DUMMY BODY */ }
160
161 future(const future&) = delete;
162
163 future(future&& rhs) noexcept
164 : aux::future_base<R>{move(rhs.state_)}
165 { /* DUMMY BODY */ }
166
167 future(aux::shared_state<R>* state)
168 : aux::future_base<R>{state}
169 { /* DUMMY BODY */ }
170
171 future& operator=(const future&) = delete;
172
173 future& operator=(future&& rhs) noexcept = default;
174
175 shared_future<R> share()
176 {
177 return shared_future<R>(move(*this));
178 }
179
180 R get()
181 {
182 assert(this->state_);
183
184 this->wait();
185
186 if (this->state_->has_exception())
187 this->state_->throw_stored_exception();
188
189 return move(this->state_->get());
190 }
191 };
192
193 template<class R>
194 class future<R&>: public aux::future_base<R*>
195 {
196 public:
197 future() noexcept
198 : aux::future_base<R*>{}
199 { /* DUMMY BODY */ }
200
201 future(const future&) = delete;
202
203 future(future&& rhs) noexcept
204 : aux::future_base<R*>{move(rhs.state_)}
205 { /* DUMMY BODY */ }
206
207 future(aux::shared_state<R*>* state)
208 : aux::future_base<R*>{state}
209 { /* DUMMY BODY */ }
210
211 future& operator=(const future&) = delete;
212
213 future& operator=(future&& rhs) noexcept = default;
214
215 shared_future<R&> share()
216 {
217 return shared_future<R&>(move(*this));
218 }
219
220 R& get()
221 {
222 assert(this->state_);
223
224 this->wait();
225
226 if (this->state_->has_exception())
227 this->state_->throw_stored_exception();
228
229 assert(this->state_->get());
230 return *this->state_->get();
231 }
232 };
233
234 template<>
235 class future<void>: public aux::future_base<void>
236 {
237 public:
238 future() noexcept
239 : aux::future_base<void>{}
240 { /* DUMMY BODY */ }
241
242 future(const future&) = delete;
243
244 future(future&& rhs) noexcept
245 : aux::future_base<void>{move(rhs.state_)}
246 { /* DUMMY BODY */ }
247
248 future(aux::shared_state<void>* state)
249 : aux::future_base<void>{state}
250 { /* DUMMY BODY */ }
251
252 future& operator=(const future&) = delete;
253
254 future& operator=(future&& rhs) noexcept = default;
255
256 /* shared_future<void> share() */
257 /* { */
258 /* return shared_future<void>(move(*this)); */
259 /* } */
260
261 void get()
262 {
263 assert(this->state_);
264
265 this->wait();
266
267 if (this->state_->has_exception())
268 this->state_->throw_stored_exception();
269 }
270 };
271}
272
273#endif
Note: See TracBrowser for help on using the repository browser.