Google Cloud C++ Client 2.10.1
C++ Client Library for Google Cloud Platform
Loading...
Searching...
No Matches
future_generic.h
1// Copyright 2018 Google LLC
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// https://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#ifndef GOOGLE_CLOUD_CPP_GOOGLE_CLOUD_FUTURE_GENERIC_H
16#define GOOGLE_CLOUD_CPP_GOOGLE_CLOUD_FUTURE_GENERIC_H
17/**
18 * @file
19 *
20 * Fully specialize `future<void>` and `promise<R>` for void.
21 */
22
23#include "google/cloud/internal/future_base.h"
24#include "google/cloud/internal/future_fwd.h"
25#include "google/cloud/internal/future_impl.h"
26#include "google/cloud/internal/future_then_meta.h"
27#include "google/cloud/version.h"
28#include "absl/meta/type_traits.h"
29
30namespace google {
31namespace cloud {
33/**
34 * Implement ISO/IEC TS 19571:2016 `future<T>`.
35 */
36template <typename T>
37class future final : private internal::future_base<T> {
38 public:
39 using shared_state_type =
40 typename internal::future_base<T>::shared_state_type;
41
42 // workaround Apple Clang-7xx series bug, if we use `= default` here, the
43 // compiler believes there is no default constructor defined. :shrug:
44 future() noexcept {} // NOLINT(modernize-use-equals-default)
45
46 /**
47 * Creates a new future that unwraps @p rhs.
48 *
49 * This constructor creates a new shared state that becomes satisfied when
50 * both `rhs` and `rhs.get()` become satisfied. If `rhs` is satisfied, but
51 * `rhs.get()` returns an invalid future then the newly created future becomes
52 * satisfied with a `std::future_error` exception, and the exception error
53 * code is `std::future_errc::broken_promise`.
54 *
55 * @note The technical specification requires this to be a `noexcept`
56 * constructor I (coryan) believe this is a defect in the technical
57 * specification, as this *creates* a new shared state: shared states are
58 * dynamically allocated, and the allocator (which might be the default
59 * `operator new`) may raise.
60 */
61 // NOLINTNEXTLINE(google-explicit-constructor)
62 future(future<future<T>>&& rhs) noexcept(false);
63
64 /**
65 * Creates a future from a future whose result type is convertible to this
66 * future's result type.
67 */
68 template <class U, typename Enable =
69 absl::enable_if_t<std::is_constructible<T, U>::value>>
70 explicit future(future<U>&& rhs)
71 : future<T>(rhs.then([](future<U> other) { return T(other.get()); })) {}
72
73 /**
74 * Waits until the shared state becomes ready, then retrieves the value stored
75 * in the shared state.
76 *
77 * @note This operation invalidates the future, subsequent calls will fail,
78 * the application should capture the returned value because it would.
79 *
80 * @throws any exceptions stored in the shared state.
81 * @throws std::future_error with std::no_state if the future does not have
82 * a shared state.
83 */
84 T get() {
85 this->check_valid();
86 std::shared_ptr<shared_state_type> tmp;
87 tmp.swap(this->shared_state_);
88 return tmp->get();
89 }
90
91 using internal::future_base<T>::cancel;
92 using internal::future_base<T>::is_ready;
93 using internal::future_base<T>::valid;
94 using internal::future_base<T>::wait;
95 using internal::future_base<T>::wait_for;
96 using internal::future_base<T>::wait_until;
97
98 /**
99 * Attach a continuation to the future.
100 *
101 * Attach a callable @a func to be invoked when the future is
102 * ready. The return type is a future wrapping the return type of
103 * @a func.
104 *
105 * @return `future<T>` where T is `std::result_of_t<F, R>` (basically).
106 * If T matches `future<U>` then it returns `future<U>`. The returned
107 * future will contain the result of @a func.
108 * @param func a Callable to be invoked when the future is ready.
109 * The function might be called immediately, e.g., if the future is
110 * ready.
111 *
112 * Side effects: `valid() == false` if the operation is successful.
113 */
114 template <typename F>
115 typename internal::then_helper<F, T>::future_t then(F&& func) {
116 this->check_valid();
117 using requires_unwrap_t =
118 typename internal::then_helper<F, T>::requires_unwrap_t;
119 return then_impl(std::forward<F>(func), requires_unwrap_t{});
120 }
121
122 explicit future(std::shared_ptr<shared_state_type> state)
123 : internal::future_base<T>(std::move(state)) {}
124
125 private:
126 /// Implement `then()` if the result does not require unwrapping.
127 template <typename F>
128 typename internal::then_helper<F, T>::future_t then_impl(F&& functor,
129 std::false_type);
130
131 /// Implement `then()` if the result requires unwrapping.
132 template <typename F>
133 typename internal::then_helper<F, T>::future_t then_impl(F&& functor,
134 std::true_type);
135
136 template <typename U>
137 friend class future;
138 friend class future<void>;
139
140 friend struct internal::CoroutineSupport;
141};
142
143/**
144 * Implement `promise<T>` as defined in ISO/IEC TS 19571:2016.
145 */
146template <typename T>
147class promise final : private internal::promise_base<T> {
148 public:
149 /// Creates a promise with an unsatisfied shared state.
150 promise() : internal::promise_base<T>([] {}) {}
151
152 /// Creates a promise with an unsatisfied shared state.
153 explicit promise(std::function<void()> cancellation_callback)
154 : internal::promise_base<T>(std::move(cancellation_callback)) {}
155
156 /// Creates a promise *without* a shared state.
157 explicit promise(null_promise_t x)
158 : internal::promise_base<T>(std::move(x)) {}
159
160 /// Constructs a new promise and transfer any shared state from @p rhs.
161 // NOLINTNEXTLINE(performance-noexcept-move-constructor)
162 promise(promise&&) = default;
163
164 /// Abandons the shared state in `*this`, if any, and transfers the shared
165 /// state from @p rhs.
166 promise& operator=(promise&& rhs) noexcept {
167 promise tmp(std::move(rhs));
168 this->swap(tmp);
169 return *this;
170 }
171
172 /**
173 * Abandons any shared state.
174 *
175 * If the shared state was not already satisfied it becomes satisfied with
176 * a `std::future_error` exception. The error code in this exception is
177 * `std::future_errc::broken_promise`.
178 */
179 ~promise() = default;
180
181 promise(promise const&) = delete;
182 promise& operator=(promise const&) = delete;
183
184 /// Swaps the shared state in `*this` with @p rhs.
185 void swap(promise& other) noexcept {
186 std::swap(this->shared_state_, other.shared_state_);
187 }
188
189 /**
190 * Creates the `future<T>` using the same shared state as `*this`.
191 */
192 future<T> get_future() {
193 internal::future_shared_state<T>::mark_retrieved(this->shared_state_);
194 return future<T>(this->shared_state_);
195 }
196
197 /**
198 * Satisfies the shared state.
199 *
200 * @throws std::future_error with std::future_errc::promise_already_satisfied
201 * if the shared state is already satisfied.
202 * @throws std::future_error with std::no_state if the promise does not have
203 * a shared state.
204 */
205 void set_value(T value) {
206 if (!this->shared_state_) {
207 internal::ThrowFutureError(std::future_errc::no_state, __func__);
208 }
209 this->shared_state_->set_value(std::move(value));
210 }
211
212 using internal::promise_base<T>::set_exception;
213};
214
215/// Create a future<void> that is immediately ready.
216template <typename T>
217inline future<typename internal::make_ready_return<T>::type> make_ready_future(
218 T&& t) {
219 using V = typename internal::make_ready_return<T>::type;
220 // TODO(#1410) - Implement specializations of future<R&> and promise<R&>.
221 static_assert(!std::is_reference<V>::value, "future<R&> is not implemented");
222 promise<V> p;
223 p.set_value(std::forward<T>(t));
224 return p.get_future();
225}
226
228} // namespace cloud
229} // namespace google
230
231#endif // GOOGLE_CLOUD_CPP_GOOGLE_CLOUD_FUTURE_GENERIC_H
future(future< U > &&rhs)
Creates a future from a future whose result type is convertible to this future's result type.
Definition: future_generic.h:70
T get()
Waits until the shared state becomes ready, then retrieves the value stored in the shared state.
Definition: future_generic.h:84
internal::then_helper< F, T >::future_t then(F &&func)
Attach a continuation to the future.
Definition: future_generic.h:115
future(std::shared_ptr< shared_state_type > state)
Definition: future_generic.h:122
friend class future
Definition: future_generic.h:137
future() noexcept
Definition: future_generic.h:44
future(future< future< T > > &&rhs) noexcept(false)
Creates a new future that unwraps rhs.
promise(promise &&)=default
Constructs a new promise and transfer any shared state from rhs.
void swap(promise &other) noexcept
Swaps the shared state in *this with rhs.
Definition: future_generic.h:185
promise()
Creates a promise with an unsatisfied shared state.
Definition: future_generic.h:150
promise(null_promise_t x)
Creates a promise without a shared state.
Definition: future_generic.h:157
promise & operator=(promise &&rhs) noexcept
Abandons the shared state in *this, if any, and transfers the shared state from rhs.
Definition: future_generic.h:166
promise & operator=(promise const &)=delete
~promise()=default
Abandons any shared state.
future< T > get_future()
Creates the future<T> using the same shared state as *this.
Definition: future_generic.h:192
promise(promise const &)=delete
promise(std::function< void()> cancellation_callback)
Creates a promise with an unsatisfied shared state.
Definition: future_generic.h:153
void set_value(T value)
Satisfies the shared state.
Definition: future_generic.h:205
Contains all the Google Cloud C++ Library APIs.
Definition: async_operation.h:23
future< typename internal::make_ready_return< T >::type > make_ready_future(T &&t)
Create a future<void> that is immediately ready.
Definition: future_generic.h:217
Definition: async_operation.h:22
#define GOOGLE_CLOUD_CPP_INLINE_NAMESPACE_END
Definition: version.h:45
#define GOOGLE_CLOUD_CPP_INLINE_NAMESPACE_BEGIN
Definition: version.h:43