This repository has been archived by the owner on Dec 8, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 10
/
future_base.h
191 lines (171 loc) · 6.42 KB
/
future_base.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
// Copyright 2018 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef GOOGLE_CLOUD_CPP_GOOGLE_CLOUD_INTERNAL_FUTURE_BASE_H
#define GOOGLE_CLOUD_CPP_GOOGLE_CLOUD_INTERNAL_FUTURE_BASE_H
/**
* @file
*
* Define the implementation details for `google::cloud::future<T>`.
*/
#include "google/cloud/internal/future_impl.h"
namespace google {
namespace cloud {
inline namespace GOOGLE_CLOUD_CPP_NS {
namespace internal {
/**
* Refactor common functions to `future<T>`, `future<R&>` and `future<void>`.
* @tparam T
*/
template <typename T>
class future_base {
public:
future_base() noexcept = default;
future_base(future_base&&) noexcept = default;
future_base& operator=(future_base&&) noexcept = default;
future_base(future_base const& rhs) = delete;
future_base& operator=(future_base const& rhs) = delete;
/// Returns true if the future has a shared state.
bool valid() const noexcept { return static_cast<bool>(shared_state_); }
/**
* Blocks until the shared state is ready.
*
* @throws std::future_error with std::future_errc::no_state if the future has
* no shared state.
*/
void wait() const {
check_valid();
shared_state_->wait();
}
/**
* Blocks until the shared state is ready, or until @p duration time has
* elapsed.
*
* @param duration the maximum time to wait for the shared state to become
* ready.
*
* @tparam Rep a placeholder to match the Rep tparam for @p duration's
* type, the semantics of this template parameter are documented in
* `std::chrono::duration<>` (in brief, the underlying arithmetic type
* used to store the number of ticks), for our purposes it is simply a
* formal parameter.
* @tparam Period a placeholder to match the Period tparam for @p duration's
* type, the semantics of this template parameter are documented in
* `std::chrono::duration<>` (in brief, the length of the tick in seconds,
* expressed as a `std::ratio<>`), for our purposes it is simply a formal
* parameter.
*
* @return `std::future_status::ready` if the shared state is satisfied.
* `std::future_status::deferred` if the shared state is not satisfied and
* there is a continuation ready to execute when it is satisfied.
* `std::future_status::timeout` otherwise.
*
* @throws std::future_error with std::future_errc::no_state if the future has
* no shared state.
*/
template <typename Rep, typename Period>
std::future_status wait_for(
std::chrono::duration<Rep, Period> const& rel_time) const {
check_valid();
return shared_state_->wait_for(rel_time);
}
/**
* Blocks until the shared state is ready, or until @p deadline expires.
*
* @param deadline a time point after which this function no longer waits.
*
* @tparam Clock a placeholder to match the Clock tparam for @p tp's
* type, the semantics of this template parameter are documented in
* `std::chrono::time_point<>` (in brief, the underlying clock type
* associated with the time point), for our purposes it is simply a
* formal parameter.
*
* @return `std::future_status::ready` if the shared state is satisfied.
* `std::future_status::deferred` if the shared state is not satisfied and
* there is a continuation ready to execute when it is satisfied.
* `std::future_status::timeout` otherwise.
*
* @throws std::future_error with std::future_errc::no_state if the future has
* no shared state.
*/
template <typename Rep, typename Period>
std::future_status wait_until(
std::chrono::time_point<Rep, Period> const& abs_time) const {
check_valid();
return shared_state_->wait_until(abs_time);
}
/**
* Return true if the future is satisfied.
*
* @throws std::future_error if the future is invalid.
*/
bool is_ready() const {
check_valid();
return shared_state_->is_ready();
}
protected:
/// Shorthand to refer to the shared state type.
using shared_state_type = internal::future_shared_state<T>;
/// Creates a future from a shared state.
explicit future_base(std::shared_ptr<shared_state_type> state)
: shared_state_(std::move(state)) {}
/// Throws an exception if the shared state is not valid.
void check_valid() const {
if (!shared_state_) {
ThrowFutureError(std::future_errc::no_state, __func__);
}
}
std::shared_ptr<shared_state_type> shared_state_;
};
template <typename T>
class promise_base {
public:
promise_base(std::function<void()> cancellation_callback = [] {})
: shared_state_(
std::make_shared<shared_state_type>(cancellation_callback)) {}
promise_base(promise_base&&) noexcept = default;
~promise_base() {
if (shared_state_) {
shared_state_->abandon();
}
}
// Delete the operators we do not want. Note that the move operator is deleted
// because the implementation must call the destructor (or at least abandon)
// on *this.
promise_base& operator=(promise_base&&) noexcept = delete;
promise_base(promise_base const&) = delete;
promise_base& operator=(promise_base const&) = delete;
/**
* Satisfies the shared state using the exception @p ex.
*
* @throws std::future_error with std::future_errc::promise_already_satisfied
* if the shared state is already satisfied.
* @throws std::future_error with std::no_state if the promise does not have
* a shared state.
*/
void set_exception(std::exception_ptr ex) {
if (!shared_state_) {
ThrowFutureError(std::future_errc::no_state, __func__);
}
shared_state_->set_exception(std::move(ex));
}
protected:
/// Shorthand to refer to the shared state type.
using shared_state_type = internal::future_shared_state<T>;
std::shared_ptr<shared_state_type> shared_state_;
};
} // namespace internal
} // namespace GOOGLE_CLOUD_CPP_NS
} // namespace cloud
} // namespace google
#endif // GOOGLE_CLOUD_CPP_GOOGLE_CLOUD_INTERNAL_FUTURE_BASE_H