]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/boost/beast/core/detail/impl/read.hpp
import quincy beta 17.1.0
[ceph.git] / ceph / src / boost / boost / beast / core / detail / impl / read.hpp
CommitLineData
92f5a8d4
TL
1//
2// Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
3//
4// Distributed under the Boost Software License, Version 1.0. (See accompanying
5// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6//
7// Official repository: https://github.com/boostorg/beast
8//
9
10#ifndef BOOST_BEAST_DETAIL_IMPL_READ_HPP
11#define BOOST_BEAST_DETAIL_IMPL_READ_HPP
12
13#include <boost/beast/core/bind_handler.hpp>
14#include <boost/beast/core/async_base.hpp>
15#include <boost/beast/core/flat_static_buffer.hpp>
16#include <boost/beast/core/read_size.hpp>
17#include <boost/asio/basic_stream_socket.hpp>
18#include <boost/asio/coroutine.hpp>
19#include <boost/throw_exception.hpp>
20
21namespace boost {
22namespace beast {
23namespace detail {
24
25// The number of bytes in the stack buffer when using non-blocking.
26static std::size_t constexpr default_max_stack_buffer = 16384;
27
28//------------------------------------------------------------------------------
29
30struct dynamic_read_ops
31{
32
33// read into a dynamic buffer until the
34// condition is met or an error occurs
35template<
36 class Stream,
37 class DynamicBuffer,
38 class Condition,
39 class Handler>
40class read_op
41 : public asio::coroutine
42 , public async_base<
43 Handler, beast::executor_type<Stream>>
44{
45 Stream& s_;
46 DynamicBuffer& b_;
47 Condition cond_;
48 error_code ec_;
49 std::size_t total_ = 0;
50
51public:
52 read_op(read_op&&) = default;
53
54 template<class Handler_, class Condition_>
55 read_op(
56 Handler_&& h,
57 Stream& s,
58 DynamicBuffer& b,
59 Condition_&& cond)
60 : async_base<Handler,
61 beast::executor_type<Stream>>(
62 std::forward<Handler_>(h),
63 s.get_executor())
64 , s_(s)
65 , b_(b)
66 , cond_(std::forward<Condition_>(cond))
67 {
68 (*this)({}, 0, false);
69 }
70
71 void
72 operator()(
73 error_code ec,
74 std::size_t bytes_transferred,
75 bool cont = true)
76 {
77 std::size_t max_prepare;
78 BOOST_ASIO_CORO_REENTER(*this)
79 {
80 for(;;)
81 {
82 max_prepare = beast::read_size(b_, cond_(ec, total_, b_));
83 if(max_prepare == 0)
84 break;
85 BOOST_ASIO_CORO_YIELD
86 s_.async_read_some(
87 b_.prepare(max_prepare), std::move(*this));
88 b_.commit(bytes_transferred);
89 total_ += bytes_transferred;
90 }
91 if(! cont)
92 {
93 // run this handler "as-if" using net::post
94 // to reduce template instantiations
95 ec_ = ec;
96 BOOST_ASIO_CORO_YIELD
97 s_.async_read_some(
98 b_.prepare(0), std::move(*this));
99 ec = ec_;
100 }
101 this->complete_now(ec, total_);
102 }
103 }
104};
105
106//------------------------------------------------------------------------------
107
108struct run_read_op
109{
110 template<
111 class AsyncReadStream,
112 class DynamicBuffer,
113 class Condition,
114 class ReadHandler>
115 void
116 operator()(
117 ReadHandler&& h,
118 AsyncReadStream* s,
119 DynamicBuffer* b,
120 Condition&& c)
121 {
122 // If you get an error on the following line it means
123 // that your handler does not meet the documented type
124 // requirements for the handler.
125
126 static_assert(
127 beast::detail::is_invocable<ReadHandler,
128 void(error_code, std::size_t)>::value,
129 "ReadHandler type requirements not met");
130
131 read_op<
132 AsyncReadStream,
133 DynamicBuffer,
134 typename std::decay<Condition>::type,
135 typename std::decay<ReadHandler>::type>(
136 std::forward<ReadHandler>(h),
137 *s,
138 *b,
139 std::forward<Condition>(c));
140 }
141
142};
143
144};
145
146//------------------------------------------------------------------------------
147
148template<
149 class SyncReadStream,
150 class DynamicBuffer,
151 class CompletionCondition,
152 class>
153std::size_t
154read(
155 SyncReadStream& stream,
156 DynamicBuffer& buffer,
157 CompletionCondition cond)
158{
159 static_assert(is_sync_read_stream<SyncReadStream>::value,
160 "SyncReadStream type requirements not met");
161 static_assert(
162 net::is_dynamic_buffer<DynamicBuffer>::value,
163 "DynamicBuffer type requirements not met");
164 static_assert(
165 detail::is_invocable<CompletionCondition,
166 void(error_code&, std::size_t, DynamicBuffer&)>::value,
167 "CompletionCondition type requirements not met");
168 error_code ec;
169 auto const bytes_transferred = detail::read(
170 stream, buffer, std::move(cond), ec);
171 if(ec)
172 BOOST_THROW_EXCEPTION(system_error{ec});
173 return bytes_transferred;
174}
175
176template<
177 class SyncReadStream,
178 class DynamicBuffer,
179 class CompletionCondition,
180 class>
181std::size_t
182read(
183 SyncReadStream& stream,
184 DynamicBuffer& buffer,
185 CompletionCondition cond,
186 error_code& ec)
187{
188 static_assert(is_sync_read_stream<SyncReadStream>::value,
189 "SyncReadStream type requirements not met");
190 static_assert(
191 net::is_dynamic_buffer<DynamicBuffer>::value,
192 "DynamicBuffer type requirements not met");
193 static_assert(
194 detail::is_invocable<CompletionCondition,
195 void(error_code&, std::size_t, DynamicBuffer&)>::value,
196 "CompletionCondition type requirements not met");
197 ec = {};
198 std::size_t total = 0;
199 std::size_t max_prepare;
200 for(;;)
201 {
202 max_prepare = beast::read_size(buffer, cond(ec, total, buffer));
203 if(max_prepare == 0)
204 break;
205 std::size_t const bytes_transferred =
206 stream.read_some(buffer.prepare(max_prepare), ec);
207 buffer.commit(bytes_transferred);
208 total += bytes_transferred;
209 }
210 return total;
211}
212
213template<
214 class AsyncReadStream,
215 class DynamicBuffer,
216 class CompletionCondition,
20effc67 217 BOOST_BEAST_ASYNC_TPARAM2 ReadHandler,
92f5a8d4
TL
218 class>
219BOOST_BEAST_ASYNC_RESULT2(ReadHandler)
220async_read(
221 AsyncReadStream& stream,
222 DynamicBuffer& buffer,
223 CompletionCondition&& cond,
224 ReadHandler&& handler)
225{
226 static_assert(is_async_read_stream<AsyncReadStream>::value,
227 "AsyncReadStream type requirements not met");
228 static_assert(
229 net::is_dynamic_buffer<DynamicBuffer>::value,
230 "DynamicBuffer type requirements not met");
231 static_assert(
232 detail::is_invocable<CompletionCondition,
233 void(error_code&, std::size_t, DynamicBuffer&)>::value,
234 "CompletionCondition type requirements not met");
235 return net::async_initiate<
236 ReadHandler,
237 void(error_code, std::size_t)>(
238 typename dynamic_read_ops::run_read_op{},
239 handler,
240 &stream,
241 &buffer,
242 std::forward<CompletionCondition>(cond));
243}
244
245} // detail
246} // beast
247} // boost
248
249#endif