63e88f80
Hu Chunming
提交三方库
|
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
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
|
//
// experimental/promise.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2021-2022 Klemens D. Morgenstern
// (klemens dot morgenstern at gmx dot net)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef BOOST_ASIO_EXPERIMENTAL_PROMISE_HPP
#define BOOST_ASIO_EXPERIMENTAL_PROMISE_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include <boost/asio/detail/config.hpp>
#include <boost/asio/detail/type_traits.hpp>
#include <boost/asio/any_io_executor.hpp>
#include <boost/asio/associated_cancellation_slot.hpp>
#include <boost/asio/associated_executor.hpp>
#include <boost/asio/bind_executor.hpp>
#include <boost/asio/cancellation_signal.hpp>
#include <boost/asio/dispatch.hpp>
#include <boost/asio/experimental/impl/promise.hpp>
#include <boost/asio/post.hpp>
#include <algorithm>
#include <boost/asio/detail/push_options.hpp>
namespace boost {
namespace asio {
namespace experimental {
template <typename T>
struct is_promise : std::false_type {};
template <typename ... Ts>
struct is_promise<promise<Ts...>> : std::true_type {};
template <typename T>
constexpr bool is_promise_v = is_promise<T>::value;
template <typename ... Ts>
struct promise_value_type
{
using type = std::tuple<Ts...>;
};
template <typename T>
struct promise_value_type<T>
{
using type = T;
};
template <>
struct promise_value_type<>
{
using type = std::tuple<>;
};
#if defined(GENERATING_DOCUMENTATION)
/// A disposable handle for an eager operation.
/**
* @tparam Signature The signature of the operation.
*
* @tparam Executor The executor to be used by the promise (taken from the
* operation).
*
* @tparam Allocator The allocator used for the promise. Can be set through
* use_allocator.
*
* A promise can be used to initiate an asynchronous option that can be
* completed later. If the promise gets destroyed before completion, the
* operation gets a cancel signal and the result is ignored.
*
* A promise fulfills the requirements of async_operation.
*
* @par Examples
* Reading and writing from one coroutine.
* @code
* awaitable<void> read_write_some(boost::asio::ip::tcp::socket & sock,
* boost::asio::mutable_buffer read_buf, boost::asio::const_buffer to_write)
* {
* auto p = boost::asio::async_read(read_buf, boost::asio::use_awaitable);
* co_await boost::asio::async_write_some(to_write, boost::asio::deferred);
* co_await p;
* }
* @endcode
*/
template<typename Signature = void(),
typename Executor = boost::asio::any_io_executor,
typename Allocator = std::allocator<void>>
struct promise
#else
template <typename ... Ts, typename Executor, typename Allocator>
struct promise<void(Ts...), Executor, Allocator>
#endif // defined(GENERATING_DOCUMENTATION)
{
/// The value that's returned by the promise.
using value_type = typename promise_value_type<Ts...>::type;
/// Cancel the promise. Usually done through the destructor.
void cancel(cancellation_type level = cancellation_type::all)
{
if (impl_ && !impl_->done)
{
boost::asio::dispatch(impl_->executor,
[level, impl = impl_]{ impl->cancel.emit(level); });
}
}
/// Check if the promise is completed already.
bool completed() const noexcept
{
return impl_ && impl_->done;
}
/// Wait for the promise to become ready.
template <BOOST_ASIO_COMPLETION_TOKEN_FOR(void(Ts...)) CompletionToken>
inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(Ts...))
operator()(CompletionToken&& token)
{
assert(impl_);
return async_initiate<CompletionToken, void(Ts...)>(
initiate_async_wait{impl_}, token);
}
promise() = delete;
promise(const promise& ) = delete;
promise(promise&& ) noexcept = default;
/// Destruct the promise and cancel the operation.
/**
* It is safe to destruct a promise of a promise that didn't complete.
*/
~promise() { cancel(); }
private:
#if !defined(GENERATING_DOCUMENTATION)
template <typename, typename, typename> friend struct promise;
friend struct detail::promise_handler<void(Ts...), Executor, Allocator>;
#endif // !defined(GENERATING_DOCUMENTATION)
std::shared_ptr<detail::promise_impl<
void(Ts...), Executor, Allocator>> impl_;
promise(
std::shared_ptr<detail::promise_impl<
void(Ts...), Executor, Allocator>> impl)
: impl_(impl)
{
}
struct initiate_async_wait
{
std::shared_ptr<detail::promise_impl<
void(Ts...), Executor, Allocator>> self_;
template <typename WaitHandler>
void operator()(WaitHandler&& handler) const
{
const auto alloc = get_associated_allocator(
handler, self_->get_allocator());
auto cancel = get_associated_cancellation_slot(handler);
if (self_->done)
{
auto exec = boost::asio::get_associated_executor(
handler, self_->get_executor());
boost::asio::post(exec,
[self = std::move(self_),
handler = std::forward<WaitHandler>(handler)]() mutable
{
self->apply(std::move(handler));
});
}
else
{
if (cancel.is_connected())
{
struct cancel_handler
{
std::weak_ptr<detail::promise_impl<
void(Ts...), Executor, Allocator>> self;
cancel_handler(
std::weak_ptr<detail::promise_impl<
void(Ts...), Executor, Allocator>> self)
: self(std::move(self))
{
}
void operator()(cancellation_type level) const
{
if (auto p = self.lock())
{
p->cancel.emit(level);
p->cancel_();
}
}
};
cancel.template emplace<cancel_handler>(self_);
}
self_->set_completion(alloc, std::forward<WaitHandler>(handler));
}
}
};
};
} // namespace experimental
} // namespace asio
} // namespace boost
#include <boost/asio/detail/pop_options.hpp>
#endif // BOOST_ASIO_EXPERIMENTAL_PROMISE_HPP
|