Google Cloud C++ Client  0.4.0
C++ Client Library for Google Cloud Platform
future_generic.h
Go to the documentation of this file.
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 // http://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 
28 namespace google {
29 namespace cloud {
30 inline namespace GOOGLE_CLOUD_CPP_NS {
31 /**
32  * Implement ISO/IEC TS 19571:2016 `future<T>`.
33  */
34 template <typename T>
35 class future final : private internal::future_base<T> {
36  public:
37  using shared_state_type =
38  typename internal::future_base<T>::shared_state_type;
39 
40  // workaround Apple Clang-7xx series bug, if we use `= default` here, the
41  // compiler believes there is no default constructor defined. :shrug:
42  future() noexcept {}
43 
44  /**
45  * Creates a new future that unwraps @p rhs.
46  *
47  * This constructor creates a new shared state that becomes satisfied when
48  * both `rhs` and `rhs.get()` become satisfied. If `rhs` is satisfied, but
49  * `rhs.get()` returns an invalid future then the newly created future becomes
50  * satisfied with a `std::future_error` exception, and the exception error
51  * code is `std::future_errc::broken_promise`.
52  *
53  * @note The technical specification requires this to be a `noexcept`
54  * constructor I (coryan) believe this is a defect in the technical
55  * specification, as this *creates* a new shared state: shared states are
56  * dynamically allocated, and the allocator (which might be the default
57  * `operator new`) may raise.
58  */
59  future(future<future<T>>&& rhs) noexcept(false);
60 
61  /**
62  * Waits until the shared state becomes ready, then retrieves the value stored
63  * in the shared state.
64  *
65  * @note This operation invalidates the future, subsequent calls will fail,
66  * the application should capture the returned value because it would.
67  *
68  * @throws any exceptions stored in the shared state.
69  * @throws std::future_error with std::no_state if the future does not have
70  * a shared state.
71  */
72  T get() {
73  this->check_valid();
74  std::shared_ptr<shared_state_type> tmp;
75  tmp.swap(this->shared_state_);
76  return tmp->get();
77  }
78 
79  using internal::future_base<T>::is_ready;
80  using internal::future_base<T>::valid;
81  using internal::future_base<T>::wait;
82  using internal::future_base<T>::wait_for;
83  using internal::future_base<T>::wait_until;
84 
85  /**
86  * Attach a continuation to the future.
87  *
88  * Attach a callable @a func to be invoked when the future is
89  * ready. The return type is a future wrapping the return type of
90  * @a func.
91  *
92  * @return future<T> where T is std::result_of_t<F, R> (basically).
93  * If T matches future<U> then it returns future<U>. The returned
94  * future will contain the result of @a func.
95  * @param func a Callable to be invoked when the future is ready.
96  * The function might be called immediately, e.g., if the future is
97  * ready.
98  *
99  * Side effects: valid() == false if the operation is successful.
100  */
101  template <typename F>
102  typename internal::then_helper<F, T>::future_t then(F&& func) {
103  this->check_valid();
104  using requires_unwrap_t =
105  typename internal::then_helper<F, T>::requires_unwrap_t;
106  return then_impl(std::forward<F>(func), requires_unwrap_t{});
107  }
108 
109  explicit future(std::shared_ptr<shared_state_type> state)
110  : internal::future_base<T>(std::move(state)) {}
111 
112  private:
113  /// Implement `then()` if the result does not require unwrapping.
114  template <typename F>
115  typename internal::then_helper<F, T>::future_t then_impl(F&& functor,
116  std::false_type);
117 
118  /// Implement `then()` if the result requires unwrapping.
119  template <typename F>
120  typename internal::then_helper<F, T>::future_t then_impl(F&& functor,
121  std::true_type);
122 
123  template <typename U>
124  friend class future;
125  friend class future<void>;
126 };
127 
128 /**
129  * Implement `promise<T>` as defined in ISO/IEC TS 19571:2016.
130  */
131 template <typename T>
132 class promise final : private internal::promise_base<T> {
133  public:
134  /// Creates a promise with an unsatisfied shared state.
135  promise() = default;
136 
137  /// Constructs a new promise and transfer any shared state from @p rhs.
138  promise(promise&& rhs) noexcept = default;
139 
140  /// Abandons the shared state in `*this`, if any, and transfers the shared
141  /// state from @p rhs.
142  promise& operator=(promise&& rhs) noexcept {
143  promise tmp(std::move(rhs));
144  this->swap(tmp);
145  return *this;
146  }
147 
148  /**
149  * Abandons any shared state.
150  *
151  * If the shared state was not already satisfied it becomes satisfied with
152  * a `std::future_error` exception. The error code in this exception is
153  * `std::future_errc::broken_promise`.
154  */
155  ~promise() = default;
156 
157  promise(promise const&) = delete;
158  promise& operator=(promise const&) = delete;
159 
160  /// Swaps the shared state in `*this` with @p rhs.
161  void swap(promise& other) noexcept {
162  std::swap(this->shared_state_, other.shared_state_);
163  }
164 
165  /**
166  * Creates the `future<T>` using the same shared state as `*this`.
167  */
169  internal::future_shared_state<T>::mark_retrieved(this->shared_state_);
170  return future<T>(this->shared_state_);
171  }
172 
173  /**
174  * Satisfies the shared state.
175  *
176  * @throws std::future_error with std::future_errc::promise_already_satisfied
177  * if the shared state is already satisfied.
178  * @throws std::future_error with std::no_state if the promise does not have
179  * a shared state.
180  */
181  void set_value(T&& value) {
182  if (!this->shared_state_) {
183  internal::ThrowFutureError(std::future_errc::no_state, __func__);
184  }
185  this->shared_state_->set_value(std::forward<T>(value));
186  }
187 
188  /**
189  * Satisfies the shared state.
190  *
191  * @throws std::future_error with std::future_errc::promise_already_satisfied
192  * if the shared state is already satisfied.
193  * @throws std::future_error with std::no_state if the promise does not have
194  * a shared state.
195  */
196  void set_value(T const& value) { set_value(T(value)); }
197 
198  using internal::promise_base<T>::set_exception;
199 };
200 
201 } // namespace GOOGLE_CLOUD_CPP_NS
202 } // namespace cloud
203 } // namespace google
204 
205 #endif // GOOGLE_CLOUD_CPP_GOOGLE_CLOUD_FUTURE_GENERIC_H_
future< T > get_future()
Creates the future<T> using the same shared state as *this.
#define GOOGLE_CLOUD_CPP_NS
Definition: version.h:24
future(std::shared_ptr< shared_state_type > state)
Contains all the Google Cloud C++ Library APIs.
Definition: iam_bindings.cc:21
promise()=default
Creates a promise with an unsatisfied shared state.
promise & operator=(promise const &)=delete
void swap(promise &other) noexcept
Swaps the shared state in *this with rhs.
promise(promise const &)=delete
T get()
Waits until the shared state becomes ready, then retrieves the value stored in the shared state...
~promise()=default
Abandons any shared state.
future(future< future< T >> &&rhs) noexcept(false)
Creates a new future that unwraps rhs.
void set_value(T const &value)
Satisfies the shared state.
promise & operator=(promise &&rhs) noexcept
Abandons the shared state in *this, if any, and transfers the shared state from rhs.
promise(promise &&rhs) noexcept=default
Constructs a new promise and transfer any shared state from rhs.
void set_value(T &&value)
Satisfies the shared state.
internal::then_helper< F, T >::future_t then(F &&func)
Attach a continuation to the future.