8
8
#include < exception>
9
9
#include < future>
10
10
#include < memory>
11
+ #include < optional>
11
12
#include < span>
12
13
#include < string_view>
13
14
#include < system_error>
19
20
#include " async_simple/Promise.h"
20
21
#include " async_simple/Signal.h"
21
22
#include " async_simple/coro/Collect.h"
23
+ #include " async_simple/coro/FutureAwaiter.h"
22
24
#include " async_simple/coro/Lazy.h"
23
25
#include " ib_buffer.hpp"
24
26
#include " ib_socket.hpp"
30
32
#include " ylt/struct_pack/reflection.hpp"
31
33
namespace coro_io {
32
34
33
- // unlike tcp socket, client won't connnected util server first read ib_socket.
34
35
inline async_simple::coro::Lazy<std::error_code> async_accept (
35
36
asio::ip::tcp::acceptor& acceptor, coro_io::ib_socket_t & ib_socket) {
36
- auto soc = std::make_unique< asio::ip::tcp::socket> (ib_socket.get_executor ());
37
+ asio::ip::tcp::socket soc (ib_socket.get_executor ());
37
38
auto ec = co_await async_io<std::error_code>(
38
39
[&](auto cb) {
39
- acceptor.async_accept (* soc, cb);
40
+ acceptor.async_accept (soc, cb);
40
41
},
41
42
acceptor);
42
43
@@ -51,24 +52,13 @@ inline async_simple::coro::Lazy<std::error_code> async_accept(
51
52
inline async_simple::coro::Lazy<std::error_code> async_connect (
52
53
coro_io::ib_socket_t & ib_socket, const std::string& host,
53
54
const std::string& port) {
54
- asio::ip::tcp::socket soc{ib_socket.get_executor ()};
55
- auto ec =
56
- co_await async_connect (ib_socket.get_coro_executor (), soc, host, port);
57
- if (ec) [[unlikely]] {
58
- co_return std::move (ec);
59
- }
60
- co_return co_await ib_socket.connect (soc);
55
+ return ib_socket.connect (host, port);
61
56
}
62
57
63
58
template <typename EndPointSeq>
64
59
inline async_simple::coro::Lazy<std::error_code> async_connect (
65
60
coro_io::ib_socket_t & ib_socket, const EndPointSeq& endpoint) noexcept {
66
- asio::ip::tcp::socket soc{ib_socket.get_executor ()};
67
- auto ec = co_await async_connect (soc, endpoint);
68
- if (ec) [[unlikely]] {
69
- co_return std::move (ec);
70
- }
71
- co_return co_await ib_socket.connect (soc);
61
+ return ib_socket.connect (endpoint);
72
62
}
73
63
74
64
namespace detail {
@@ -138,32 +128,64 @@ async_simple::coro::
138
128
async_simple::coro::
139
129
Lazy<std::pair<std::error_code, std::size_t >> inline async_send_impl (
140
130
coro_io::ib_socket_t & ib_socket, std::span<ibv_sge> sge_list,
141
- std::size_t io_size) {
142
- std::vector<ib_buffer_t > tmp_buffers;
131
+ std::size_t io_size,
132
+ std::optional<
133
+ async_simple::Future<std::pair<std::error_code, std::size_t >>>&
134
+ prev_op) {
135
+ if (io_size == 0 ) [[unlikely]] {
136
+ co_return std::pair{std::error_code{}, 0 };
137
+ }
138
+ ib_buffer_t buffer;
143
139
ibv_sge socket_buffer;
144
- socket_buffer = ib_socket.get_send_buffer ();
145
- if (socket_buffer.length == 0 ) [[unlikely]] {
146
- co_return std::pair{std::make_error_code (std::errc::no_buffer_space),
147
- std::size_t {0 }};
140
+ std::span<ibv_sge> list;
141
+ if (ib_socket.get_config ().cap .max_inline_data >= io_size) {
142
+ if (sge_list.size () <= ib_socket.get_config ().cap .max_send_sge ) {
143
+ list = sge_list;
144
+ }
145
+ }
146
+ else {
147
+ buffer = ib_socket.buffer_pool ()->get_buffer ();
148
+ if (!buffer || buffer->length < io_size) [[unlikely]] {
149
+ co_return std::pair{std::make_error_code (std::errc::no_buffer_space),
150
+ std::size_t {0 }};
151
+ }
152
+ socket_buffer = buffer.subview ();
153
+ auto len = copy (sge_list, socket_buffer);
154
+ assert (len == io_size);
155
+ socket_buffer.length = io_size;
156
+ list = {&socket_buffer, 1 };
148
157
}
149
158
150
- auto len = copy (sge_list, socket_buffer);
151
- assert (len == io_size);
152
-
153
- std::span<ibv_sge> io_buffer;
154
- io_buffer = {&socket_buffer, 1 };
155
- socket_buffer.length = io_size;
156
- auto result =
157
- co_await coro_io::async_io<std::pair<std::error_code, std::size_t >>(
158
- [&](auto && cb) {
159
- ib_socket.post_send (io_buffer, std::move (cb));
160
- },
161
- ib_socket);
162
- if (result.first ) [[unlikely]] {
163
- co_return std::pair{result.first , result.second };
159
+ async_simple::Promise<std::pair<std::error_code, std::size_t >> promise;
160
+ std::pair<std::error_code, std::size_t > result{};
161
+ if (prev_op) {
162
+ result = co_await std::move (*prev_op);
163
+ }
164
+ prev_op = promise.getFuture ();
165
+ auto slot = co_await async_simple::coro::CurrentSlot{};
166
+ auto work = coro_io::async_io<std::pair<std::error_code, std::size_t >>(
167
+ [&ib_socket, list](auto && cb) mutable {
168
+ ib_socket.post_send (list, std::move (cb));
169
+ },
170
+ ib_socket);
171
+ auto cb = [p = std::move (promise), io_size = io_size,
172
+ buffer = std::move (buffer)](auto && result) mutable {
173
+ if (buffer) {
174
+ std::move (buffer).collect ();
175
+ }
176
+ if (!result.hasError ()) {
177
+ result.value ().second = io_size;
178
+ }
179
+ p.setValue (std::move (result));
180
+ };
181
+ if (slot) {
182
+ std::move (work).setLazyLocal (slot->signal ()).start (std::move (cb));
183
+ }
184
+ else {
185
+ std::move (work).start (std::move (cb));
164
186
}
165
187
166
- co_return std::pair{result.first , io_size };
188
+ co_return std::pair{result.first , result. second };
167
189
}
168
190
169
191
template <typename T>
@@ -258,6 +280,8 @@ async_io_split(coro_io::ib_socket_t& ib_socket, Buffer&& raw_buffer,
258
280
259
281
std::size_t block_size;
260
282
uint32_t now_split_size = 0 ;
283
+ std::optional<async_simple::Future<std::pair<std::error_code, std::size_t >>>
284
+ future;
261
285
for (auto & sge : sge_span) {
262
286
for (std::size_t i = 0 ; i < sge.length ; i += block_size) {
263
287
block_size =
@@ -284,47 +308,45 @@ async_io_split(coro_io::ib_socket_t& ib_socket, Buffer&& raw_buffer,
284
308
}
285
309
else {
286
310
std::tie (ec, len) = co_await async_send_impl (
287
- ib_socket, split_sge_block, now_split_size);
311
+ ib_socket, split_sge_block, now_split_size, future );
288
312
}
289
-
290
313
io_completed_size += len;
291
314
ELOG_TRACE << " has completed size:" << io_completed_size;
292
315
if (ec) {
293
316
co_return std::pair{ec, io_completed_size};
294
317
}
295
318
296
- if (len == 0 || len > now_split_size) [[unlikely]] {
297
- ELOG_ERROR << " read size error, it shouldn't be:" << len;
298
- co_return std::pair{std::make_error_code (std::errc::io_error),
299
- io_completed_size};
300
- }
301
-
302
- if (read_some) {
303
- co_return std::pair{ec, io_completed_size};
304
- }
305
-
306
- if (len < now_split_size) [[unlikely]] {
307
- reset_buffer (split_sge_block, len);
319
+ if constexpr (io == ib_socket_t ::io_type::recv) {
320
+ if (read_some) {
321
+ co_return std::pair{ec, io_completed_size};
322
+ }
323
+ if (len < now_split_size) [[unlikely]] {
324
+ reset_buffer (split_sge_block, len);
325
+ }
326
+ else {
327
+ split_sge_block.clear ();
328
+ }
329
+ now_split_size -= len;
308
330
}
309
331
else {
310
332
split_sge_block.clear ();
333
+ now_split_size = 0 ;
311
334
}
312
- now_split_size -= len;
313
335
}
314
336
}
315
337
}
316
338
317
339
std::error_code ec;
318
340
std::size_t len = 0 ;
319
341
while (now_split_size > 0 ) {
320
- reset_buffer (split_sge_block, len);
321
342
if constexpr (io == ib_socket_t ::io_type::recv) {
343
+ reset_buffer (split_sge_block, len);
322
344
std::tie (ec, len) =
323
345
co_await async_recv_impl (ib_socket, split_sge_block, now_split_size);
324
346
}
325
347
else {
326
- std::tie (ec, len) =
327
- co_await async_send_impl (ib_socket, split_sge_block, now_split_size);
348
+ std::tie (ec, len) = co_await async_send_impl (ib_socket, split_sge_block,
349
+ now_split_size, future );
328
350
}
329
351
330
352
io_completed_size += len;
@@ -333,17 +355,24 @@ async_io_split(coro_io::ib_socket_t& ib_socket, Buffer&& raw_buffer,
333
355
co_return std::pair{ec, io_completed_size};
334
356
}
335
357
336
- if (len == 0 || len > now_split_size) [[unlikely]] {
337
- ELOG_ERROR << ((io == ib_socket_t ::io_type::recv) ? " recv " : " send " )
338
- << " size error, it shouldn't be: " << len ;
339
- co_return std::pair{ std::make_error_code (std::errc::io_error),
340
- io_completed_size} ;
358
+ if constexpr (io == ib_socket_t ::io_type::recv) {
359
+ if (read_some) {
360
+ co_return std::pair{ec, io_completed_size} ;
361
+ }
362
+ now_split_size -= len ;
341
363
}
342
-
343
- if (read_some) {
344
- co_return std::pair{ec, io_completed_size};
364
+ else {
365
+ now_split_size = 0 ;
366
+ }
367
+ }
368
+ if constexpr (io == ib_socket_t ::io_type::send) {
369
+ if (future) {
370
+ std::tie (ec, len) = co_await std::move (*future);
371
+ io_completed_size += len;
372
+ if (ec) [[unlikely]] {
373
+ co_return std::pair{ec, io_completed_size};
374
+ }
345
375
}
346
- now_split_size -= len;
347
376
}
348
377
co_return std::pair{ec, io_completed_size};
349
378
}
0 commit comments