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

Last change on this file since b57ba05 was b57ba05, checked in by Jiří Zárevúcky <zarevucky.jiri@…>, 3 years ago

Update headers in C++ files

  • Property mode set to 100644
File size: 6.3 KB
Line 
1/*
2 * SPDX-FileCopyrightText: 2019 Jaroslav Jindrak
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#ifndef LIBCPP_BITS_THREAD_FUTURE
8#define LIBCPP_BITS_THREAD_FUTURE
9
10#include <__bits/thread/future_common.hpp>
11#include <__bits/thread/shared_state.hpp>
12#include <__bits/utility/forward_move.hpp>
13#include <cassert>
14
15namespace std
16{
17 /**
18 * 30.6.6, class template future:
19 */
20
21 namespace aux
22 {
23 /**
24 * Note: Because of shared_future, this base class
25 * does implement copy constructor and copy
26 * assignment operator. This means that the
27 * children (std::future) need to delete this
28 * constructor and operator themselves.
29 */
30 template<class R>
31 class future_base
32 {
33 public:
34 future_base() noexcept
35 : state_{nullptr}
36 { /* DUMMY BODY */ }
37
38 future_base(const future_base& rhs)
39 : state_{rhs.state_}
40 {
41 state_->increment();
42 }
43
44 future_base(future_base&& rhs) noexcept
45 : state_{move(rhs.state_)}
46 {
47 rhs.state_ = nullptr;
48 }
49
50 future_base(aux::shared_state<R>* state)
51 : state_{state}
52 {
53 /**
54 * Note: This is a custom non-standard constructor that allows
55 * us to create a future directly from a shared state. This
56 * should never be a problem as aux::shared_state is a private
57 * type and future has no constructor templates.
58 */
59 }
60
61 virtual ~future_base()
62 {
63 release_state_();
64 }
65
66 future_base& operator=(const future_base& rhs)
67 {
68 release_state_();
69 state_ = rhs.state_;
70
71 state_->increment();
72
73 return *this;
74 }
75
76 future_base& operator=(future_base&& rhs) noexcept
77 {
78 release_state_();
79 state_ = move(rhs.state_);
80 rhs.state_ = nullptr;
81
82 return *this;
83 }
84
85 bool valid() const noexcept
86 {
87 return state_ != nullptr;
88 }
89
90 void wait() const noexcept
91 {
92 assert(state_);
93
94 state_->wait();
95 }
96
97 template<class Rep, class Period>
98 future_status
99 wait_for(const chrono::duration<Rep, Period>& rel_time) const
100 {
101 assert(state_);
102
103 return state_->wait_for(rel_time);
104 }
105
106 template<class Clock, class Duration>
107 future_status
108 wait_until(
109 const chrono::time_point<Clock, Duration>& abs_time
110 ) const
111 {
112 assert(state_);
113
114 return state_->wait_until(abs_time);
115 }
116
117 protected:
118 void release_state_()
119 {
120 if (!state_)
121 return;
122
123 /**
124 * Note: This is the 'release' move described in
125 * 30.6.4 (5).
126 * Last reference to state -> destroy state.
127 * Decrement refcount of state otherwise.
128 * Will not block, unless all following hold:
129 * 1) State was created by call to std::async.
130 * 2) State is not yet ready.
131 * 3) This was the last reference to the shared state.
132 */
133 if (state_->decrement())
134 {
135 /**
136 * The destroy call handles the special case
137 * when 1) - 3) hold.
138 */
139 state_->destroy();
140 delete state_;
141 state_ = nullptr;
142 }
143 }
144
145 aux::shared_state<R>* state_;
146 };
147 }
148
149 template<class R>
150 class shared_future;
151
152 template<class R>
153 class future: public aux::future_base<aux::future_inner_t<R>>
154 {
155 friend class shared_future<R>;
156
157 public:
158 future() noexcept
159 : aux::future_base<aux::future_inner_t<R>>{}
160 { /* DUMMY BODY */ }
161
162 future(const future&) = delete;
163
164 future(future&& rhs) noexcept
165 : aux::future_base<aux::future_inner_t<R>>{move(rhs)}
166 { /* DUMMY BODY */ }
167
168 future(aux::shared_state<aux::future_inner_t<R>>* state)
169 : aux::future_base<aux::future_inner_t<R>>{state}
170 { /* DUMMY BODY */ }
171
172 future& operator=(const future&) = delete;
173
174 future& operator=(future&& rhs) noexcept = default;
175
176 shared_future<R> share()
177 {
178 return shared_future<R>{move(*this)};
179 }
180
181 R get()
182 {
183 assert(this->state_);
184
185 this->wait();
186
187 if (this->state_->has_exception())
188 this->state_->throw_stored_exception();
189
190 if constexpr (!is_same_v<R, void>)
191 {
192 if constexpr (is_reference_v<R>)
193 {
194 assert(this->state_->get());
195
196 return *this->state_->get();
197 }
198 else
199 return this->state_->get();
200 }
201 }
202
203 /**
204 * Useful for testing as we can check some information
205 * otherwise unavailable to us without waiting, e.g.
206 * to check whether the state is ready, its reference
207 * count etc.
208 */
209 aux::shared_state<aux::future_inner_t<R>>* __state() noexcept
210 {
211 return this->state_;
212 }
213 };
214}
215
216#endif
Note: See TracBrowser for help on using the repository browser.