Condy v1.9
C++ Asynchronous System Call Layer for Linux
Loading...
Searching...
No Matches
async_operations.hpp
Go to the documentation of this file.
1
8
9#pragma once
10
12#include "condy/concepts.hpp"
13#include "condy/condy_uring.hpp"
16#include "condy/zcrx.hpp"
17
18namespace condy {
19
22
23namespace detail {
24
25class BundledProvidedBufferQueue;
26class BundledProvidedBufferPool;
27
28} // namespace detail
29
33template <FdLike Fd1, FdLike Fd2>
34inline auto async_splice(Fd1 fd_in, int64_t off_in, Fd2 fd_out, int64_t off_out,
35 unsigned int nbytes, unsigned int splice_flags) {
36 if constexpr (detail::is_fixed_fd_v<Fd1>) {
37 splice_flags |= SPLICE_F_FD_IN_FIXED;
38 }
39 auto op = detail::make_op_awaiter(io_uring_prep_splice, fd_in, off_in,
40 fd_out, off_out, nbytes, splice_flags);
41 return detail::maybe_flag_fixed_fd(std::move(op), fd_out);
42}
43
47template <FdLike Fd1, FdLike Fd2>
48inline auto async_tee(Fd1 fd_in, Fd2 fd_out, unsigned int nbytes,
49 unsigned int splice_flags) {
50 if constexpr (detail::is_fixed_fd_v<Fd1>) {
51 splice_flags |= SPLICE_F_FD_IN_FIXED;
52 }
53 auto op = detail::make_op_awaiter(io_uring_prep_tee, fd_in, fd_out, nbytes,
54 splice_flags);
55 return detail::maybe_flag_fixed_fd(std::move(op), fd_out);
56}
57
61template <FdLike Fd>
62inline auto async_readv(Fd fd, const struct iovec *iovecs, unsigned nr_vecs,
63 __u64 offset, int flags) {
64 auto op = detail::make_op_awaiter(io_uring_prep_readv2, fd, iovecs, nr_vecs,
65 offset, flags);
66 return detail::maybe_flag_fixed_fd(std::move(op), fd);
67}
68
69#if CONDY_URING_VERSION_GE(2, 10) // >= 2.10
73template <FdLike Fd>
74inline auto async_readv(Fd fd, detail::FixedBuffer<const iovec *> iovecs,
75 unsigned nr_vecs, __u64 offset, int flags) {
76 auto op =
77 detail::make_op_awaiter(io_uring_prep_readv_fixed, fd, iovecs.value,
78 nr_vecs, offset, flags, iovecs.buf_index);
79 return detail::maybe_flag_fixed_fd(std::move(op), fd);
80}
81#endif
82
83template <FdLike Fd>
87inline auto async_writev(Fd fd, const struct iovec *iovecs,
88 unsigned int nr_vecs, __u64 offset, int flags) {
89 auto op = detail::make_op_awaiter(io_uring_prep_writev2, fd, iovecs,
90 nr_vecs, offset, flags);
91 return detail::maybe_flag_fixed_fd(std::move(op), fd);
92}
93
94#if CONDY_URING_VERSION_GE(2, 10) // >= 2.10
98template <FdLike Fd>
99inline auto async_writev(Fd fd, detail::FixedBuffer<const iovec *> iovecs,
100 unsigned int nr_vecs, __u64 offset, int flags) {
101 auto op =
102 detail::make_op_awaiter(io_uring_prep_writev_fixed, fd, iovecs.value,
103 nr_vecs, offset, flags, iovecs.buf_index);
104 return detail::maybe_flag_fixed_fd(std::move(op), fd);
105}
106#endif
107
111template <FdLike Fd>
112inline auto async_recvmsg(Fd fd, struct msghdr *msg, unsigned flags) {
113 auto op = detail::make_op_awaiter(io_uring_prep_recvmsg, fd, msg, flags);
114 return detail::maybe_flag_fixed_fd(std::move(op), fd);
115}
116
120template <FdLike Fd, typename MultiShotFunc,
121 AnySameAs<ProvidedBufferQueue, ProvidedBufferPool> Buffer>
122inline auto async_recvmsg_multishot(Fd fd, struct msghdr *msg, unsigned flags,
123 Buffer &buf, MultiShotFunc &&func) {
124 auto op = detail::make_multishot_select_buffer_op_awaiter(
125 std::forward<MultiShotFunc>(func), &buf,
126 io_uring_prep_recvmsg_multishot, fd, msg, flags);
127 return detail::maybe_flag_fixed_fd(std::move(op), fd);
128}
129
133template <FdLike Fd>
134inline auto async_sendmsg(Fd fd, const struct msghdr *msg, unsigned flags) {
135 auto op = detail::make_op_awaiter(io_uring_prep_sendmsg, fd, msg, flags);
136 return detail::maybe_flag_fixed_fd(std::move(op), fd);
137}
138
142template <FdLike Fd, typename FreeFunc>
143inline auto async_sendmsg_zc(Fd fd, const struct msghdr *msg, unsigned flags,
144 FreeFunc &&func) {
145 auto op = detail::make_zero_copy_op_awaiter(
146 std::forward<FreeFunc>(func), io_uring_prep_sendmsg_zc, fd, msg, flags);
147 return detail::maybe_flag_fixed_fd(std::move(op), fd);
148}
149
150#if CONDY_URING_VERSION_GE(2, 10) // >= 2.10
154template <FdLike Fd, typename FreeFunc>
155inline auto async_sendmsg_zc(Fd fd, detail::FixedBuffer<const msghdr *> msg,
156 unsigned flags, FreeFunc &&func) {
157 auto op = detail::make_zero_copy_op_awaiter(
158 std::forward<FreeFunc>(func), io_uring_prep_sendmsg_zc_fixed, fd,
159 msg.value, flags, msg.buf_index);
160 return detail::maybe_flag_fixed_fd(std::move(op), fd);
161}
162#endif
163
167template <FdLike Fd> inline auto async_fsync(Fd fd, unsigned fsync_flags) {
168 auto op = detail::make_op_awaiter(io_uring_prep_fsync, fd, fsync_flags);
169 return detail::maybe_flag_fixed_fd(std::move(op), fd);
170}
171
175inline auto async_nop() { return detail::make_op_awaiter(io_uring_prep_nop); }
176
177#if CONDY_URING_VERSION_GE(2, 13) // >= 2.13
181inline auto async_nop128() {
182 return detail::make_op_awaiter128(io_uring_prep_nop128);
183}
184#endif
185
189inline auto async_timeout(struct __kernel_timespec *ts, unsigned count,
190 unsigned flags) {
191 return detail::make_op_awaiter(io_uring_prep_timeout, ts, count, flags);
192}
193
194#if CONDY_URING_VERSION_GE(2, 4) // >= 2.4
195
199template <typename MultiShotFunc>
200inline auto async_timeout_multishot(struct __kernel_timespec *ts,
201 unsigned count, unsigned flags,
202 MultiShotFunc &&func) {
203 return detail::make_multishot_op_awaiter(std::forward<MultiShotFunc>(func),
204 io_uring_prep_timeout, ts, count,
205 flags | IORING_TIMEOUT_MULTISHOT);
206}
207#endif
208
212template <FdLike Fd>
213inline auto async_accept(Fd fd, struct sockaddr *addr, socklen_t *addrlen,
214 int flags) {
215 auto op =
216 detail::make_op_awaiter(io_uring_prep_accept, fd, addr, addrlen, flags);
217 return detail::maybe_flag_fixed_fd(std::move(op), fd);
218}
219
223template <FdLike Fd>
224inline auto async_accept_direct(Fd fd, struct sockaddr *addr,
225 socklen_t *addrlen, int flags,
226 unsigned int file_index) {
227 auto op = detail::make_op_awaiter(io_uring_prep_accept_direct, fd, addr,
228 addrlen, flags, file_index);
229 return detail::maybe_flag_fixed_fd(std::move(op), fd);
230}
231
235template <FdLike Fd, typename MultiShotFunc>
236inline auto async_multishot_accept(Fd fd, struct sockaddr *addr,
237 socklen_t *addrlen, int flags,
238 MultiShotFunc &&func) {
239 auto op = detail::make_multishot_op_awaiter(
240 std::forward<MultiShotFunc>(func), io_uring_prep_multishot_accept, fd,
241 addr, addrlen, flags);
242 return detail::maybe_flag_fixed_fd(std::move(op), fd);
243}
244
248template <FdLike Fd, typename MultiShotFunc>
249inline auto async_multishot_accept_direct(Fd fd, struct sockaddr *addr,
250 socklen_t *addrlen, int flags,
251 MultiShotFunc &&func) {
252 auto op = detail::make_multishot_op_awaiter(
253 std::forward<MultiShotFunc>(func),
254 io_uring_prep_multishot_accept_direct, fd, addr, addrlen, flags);
255 return detail::maybe_flag_fixed_fd(std::move(op), fd);
256}
257
261template <FdLike Fd> inline auto async_cancel_fd(Fd fd, unsigned int flags) {
262 if constexpr (detail::is_fixed_fd_v<Fd>) {
263 flags |= IORING_ASYNC_CANCEL_FD_FIXED;
264 }
265 return detail::make_op_awaiter(io_uring_prep_cancel_fd, fd, flags);
266}
267
271inline auto async_link_timeout(struct __kernel_timespec *ts, unsigned flags) {
272 return detail::make_op_awaiter(io_uring_prep_link_timeout, ts, flags);
273}
274
278template <FdLike Fd>
279inline auto async_connect(Fd fd, const struct sockaddr *addr,
280 socklen_t addrlen) {
281 auto op = detail::make_op_awaiter(io_uring_prep_connect, fd, addr, addrlen);
282 return detail::maybe_flag_fixed_fd(std::move(op), fd);
283}
284
288inline auto async_files_update(int *fds, unsigned nr_fds, int offset) {
289 return detail::make_op_awaiter(io_uring_prep_files_update, fds, nr_fds,
290 offset);
291}
292
296template <FdLike Fd>
297inline auto async_fallocate(Fd fd, int mode, __u64 offset, __u64 len) {
298 auto op =
299 detail::make_op_awaiter(io_uring_prep_fallocate, fd, mode, offset, len);
300 return detail::maybe_flag_fixed_fd(std::move(op), fd);
301}
302
306inline auto async_openat(int dfd, const char *path, int flags, mode_t mode) {
307 return detail::make_op_awaiter(io_uring_prep_openat, dfd, path, flags,
308 mode);
309}
310
314inline auto async_openat_direct(int dfd, const char *path, int flags,
315 mode_t mode, unsigned file_index) {
316 return detail::make_op_awaiter(io_uring_prep_openat_direct, dfd, path,
317 flags, mode, file_index);
318}
319
323inline auto async_open(const char *path, int flags, mode_t mode) {
324 return async_openat(AT_FDCWD, path, flags, mode);
325}
326
330inline auto async_open_direct(const char *path, int flags, mode_t mode,
331 unsigned file_index) {
332 return async_openat_direct(AT_FDCWD, path, flags, mode, file_index);
333}
334
338inline auto async_close(int fd) {
339 return detail::make_op_awaiter(io_uring_prep_close, fd);
340}
341
345inline auto async_close(detail::FixedFd fd) {
346 return detail::make_op_awaiter(io_uring_prep_close_direct, fd);
347}
348
352template <FdLike Fd, BufferLike Buffer>
353inline auto async_read(Fd fd, const Buffer &buf, __u64 offset, int flags = 0) {
354 auto op = detail::make_op_awaiter(detail::prep_read, fd, buf.data(),
355 buf.size(), offset, flags);
356 return detail::maybe_flag_fixed_fd(std::move(op), fd);
357}
358
362template <FdLike Fd, BufferLike Buffer>
363inline auto async_read(Fd fd, detail::FixedBuffer<Buffer> buf, __u64 offset,
364 int flags = 0) {
365 auto op =
366 detail::make_op_awaiter(detail::prep_read_fixed, fd, buf.value.data(),
367 buf.value.size(), offset, flags, buf.buf_index);
368 return detail::maybe_flag_fixed_fd(std::move(op), fd);
369}
370
374template <FdLike Fd, AnySameAs<ProvidedBufferQueue, ProvidedBufferPool> Buffer>
375inline auto async_read(Fd fd, Buffer &buf, __u64 offset) {
376 auto op = detail::make_select_buffer_op_awaiter(&buf, io_uring_prep_read,
377 fd, nullptr, 0, offset);
378 return detail::maybe_flag_fixed_fd(std::move(op), fd);
379}
380
381#if CONDY_URING_VERSION_GE(2, 6) // >= 2.6
385template <FdLike Fd, AnySameAs<ProvidedBufferQueue, ProvidedBufferPool> Buffer,
386 typename MultiShotFunc>
387inline auto async_read_multishot(Fd fd, Buffer &buf, __u64 offset,
388 MultiShotFunc &&func) {
389 auto op = detail::make_multishot_select_buffer_op_awaiter(
390 std::forward<MultiShotFunc>(func), &buf, io_uring_prep_read_multishot,
391 fd, 0, offset, buf.bgid());
392 return detail::maybe_flag_fixed_fd(std::move(op), fd);
393}
394#endif
395
399template <FdLike Fd, BufferLike Buffer>
400inline auto async_write(Fd fd, const Buffer &buf, __u64 offset, int flags = 0) {
401 auto op = detail::make_op_awaiter(detail::prep_write, fd, buf.data(),
402 buf.size(), offset, flags);
403 return detail::maybe_flag_fixed_fd(std::move(op), fd);
404}
405
409template <FdLike Fd, BufferLike Buffer>
410inline auto async_write(Fd fd, detail::FixedBuffer<Buffer> buf, __u64 offset,
411 int flags = 0) {
412 auto op =
413 detail::make_op_awaiter(detail::prep_write_fixed, fd, buf.value.data(),
414 buf.value.size(), offset, flags, buf.buf_index);
415 return detail::maybe_flag_fixed_fd(std::move(op), fd);
416}
417
421inline auto async_statx(int dfd, const char *path, int flags, unsigned mask,
422 struct statx *statxbuf) {
423 return detail::make_op_awaiter(io_uring_prep_statx, dfd, path, flags, mask,
424 statxbuf);
425}
426
430template <FdLike Fd>
431inline auto async_fadvise(Fd fd, __u64 offset, off_t len, int advice) {
432 auto op =
433 detail::make_op_awaiter(io_uring_prep_fadvise, fd, offset, len, advice);
434 return detail::maybe_flag_fixed_fd(std::move(op), fd);
435}
436
437#if CONDY_URING_VERSION_GE(2, 7) // >= 2.7
441template <FdLike Fd>
442inline auto async_fadvise64(Fd fd, __u64 offset, off_t len, int advice) {
443 auto op = detail::make_op_awaiter(io_uring_prep_fadvise64, fd, offset, len,
444 advice);
445 return detail::maybe_flag_fixed_fd(std::move(op), fd);
446}
447#endif
448
452inline auto async_madvise(void *addr, __u32 length, int advice) {
453 return detail::make_op_awaiter(io_uring_prep_madvise, addr, length, advice);
454}
455
456#if CONDY_URING_VERSION_GE(2, 7) // >= 2.7
460inline auto async_madvise64(void *addr, off_t length, int advice) {
461 auto op =
462 detail::make_op_awaiter(io_uring_prep_madvise64, addr, length, advice);
463 return op;
464}
465#endif
466
470template <FdLike Fd, BufferLike Buffer>
471inline auto async_send(Fd sockfd, const Buffer &buf, int flags) {
472 auto op = detail::make_op_awaiter(io_uring_prep_send, sockfd, buf.data(),
473 buf.size(), flags);
474 return detail::maybe_flag_fixed_fd(std::move(op), sockfd);
475}
476
480template <FdLike Fd, BufferLike Buffer>
481inline auto async_send(Fd sockfd, detail::FixedBuffer<Buffer> buf, int flags) {
482 auto op = detail::make_op_awaiter(detail::prep_send_fixed, sockfd,
483 buf.value.data(), buf.value.size(), flags,
484 buf.buf_index);
485 return detail::maybe_flag_fixed_fd(std::move(op), sockfd);
486}
487
491template <FdLike Fd>
492inline auto async_send(Fd sockfd, ProvidedBufferQueue &buf, int flags) {
493 auto op = detail::make_select_buffer_op_awaiter(&buf, io_uring_prep_send,
494 sockfd, nullptr, 0, flags);
495 return detail::maybe_flag_fixed_fd(std::move(op), sockfd);
496}
497
498#if CONDY_URING_VERSION_GE(2, 7) // >= 2.7
502template <FdLike Fd>
503inline auto async_send(Fd sockfd, detail::BundledProvidedBufferQueue &buf,
504 int flags) {
505 auto op = detail::make_bundle_select_buffer_op_awaiter(
506 &buf, io_uring_prep_send, sockfd, nullptr, 0, flags);
507 return detail::maybe_flag_fixed_fd(std::move(op), sockfd);
508}
509#endif
510
514template <FdLike Fd, BufferLike Buffer>
515inline auto async_sendto(Fd sockfd, const Buffer &buf, int flags,
516 const struct sockaddr *addr, socklen_t addrlen) {
517 auto op = detail::make_op_awaiter(detail::prep_sendto, sockfd, buf.data(),
518 buf.size(), flags, addr, addrlen);
519 return detail::maybe_flag_fixed_fd(std::move(op), sockfd);
520}
521
525template <FdLike Fd, BufferLike Buffer>
526inline auto async_sendto(Fd sockfd, detail::FixedBuffer<Buffer> buf, int flags,
527 const struct sockaddr *addr, socklen_t addrlen) {
528 auto op = detail::make_op_awaiter(detail::prep_sendto_fixed, sockfd,
529 buf.value.data(), buf.value.size(), flags,
530 addr, addrlen, buf.buf_index);
531 return detail::maybe_flag_fixed_fd(std::move(op), sockfd);
532}
533
537template <FdLike Fd>
538inline auto async_sendto(Fd sockfd, ProvidedBufferQueue &buf, int flags,
539 const struct sockaddr *addr, socklen_t addrlen) {
540 auto op = detail::make_select_buffer_op_awaiter(
541 &buf, detail::prep_sendto, sockfd, nullptr, 0, flags, addr, addrlen);
542 return detail::maybe_flag_fixed_fd(std::move(op), sockfd);
543}
544
545#if CONDY_URING_VERSION_GE(2, 7) // >= 2.7
549template <FdLike Fd>
550inline auto async_sendto(Fd sockfd, detail::BundledProvidedBufferQueue &buf,
551 int flags, const struct sockaddr *addr,
552 socklen_t addrlen) {
553 auto op = detail::make_bundle_select_buffer_op_awaiter(
554 &buf, detail::prep_sendto, sockfd, nullptr, 0, flags, addr, addrlen);
555 return detail::maybe_flag_fixed_fd(std::move(op), sockfd);
556}
557#endif
558
562template <FdLike Fd, typename Buffer, typename FreeFunc>
563inline auto async_send_zc(Fd sockfd, const Buffer &buf, int flags,
564 unsigned zc_flags, FreeFunc &&func) {
565 auto op = detail::make_zero_copy_op_awaiter(
566 std::forward<FreeFunc>(func), io_uring_prep_send_zc, sockfd, buf.data(),
567 buf.size(), flags, zc_flags);
568 return detail::maybe_flag_fixed_fd(std::move(op), sockfd);
569}
570
574template <FdLike Fd, BufferLike Buffer, typename FreeFunc>
575inline auto async_send_zc(Fd sockfd, detail::FixedBuffer<Buffer> buf, int flags,
576 unsigned zc_flags, FreeFunc &&func) {
577 auto op = detail::make_zero_copy_op_awaiter(
578 std::forward<FreeFunc>(func), io_uring_prep_send_zc_fixed, sockfd,
579 buf.value.data(), buf.value.size(), flags, zc_flags, buf.buf_index);
580 return detail::maybe_flag_fixed_fd(std::move(op), sockfd);
581}
582
586template <FdLike Fd, BufferLike Buffer, typename FreeFunc>
587inline auto async_sendto_zc(Fd sockfd, const Buffer &buf, int flags,
588 const struct sockaddr *addr, socklen_t addrlen,
589 unsigned zc_flags, FreeFunc &&func) {
590 auto op = detail::make_zero_copy_op_awaiter(
591 std::forward<FreeFunc>(func), detail::prep_sendto_zc, sockfd,
592 buf.data(), buf.size(), flags, addr, addrlen, zc_flags);
593 return detail::maybe_flag_fixed_fd(std::move(op), sockfd);
594}
595
599template <FdLike Fd, BufferLike Buffer, typename FreeFunc>
600inline auto async_sendto_zc(Fd sockfd, detail::FixedBuffer<Buffer> buf,
601 int flags, const struct sockaddr *addr,
602 socklen_t addrlen, unsigned zc_flags,
603 FreeFunc &&func) {
604 auto op = detail::make_zero_copy_op_awaiter(
605 std::forward<FreeFunc>(func), detail::prep_sendto_zc_fixed, sockfd,
606 buf.value.data(), buf.value.size(), flags, addr, addrlen, zc_flags,
607 buf.buf_index);
608 return detail::maybe_flag_fixed_fd(std::move(op), sockfd);
609}
610
614template <FdLike Fd, BufferLike Buffer>
615inline auto async_recv(Fd sockfd, const Buffer &buf, int flags) {
616 auto op = detail::make_op_awaiter(io_uring_prep_recv, sockfd, buf.data(),
617 buf.size(), flags);
618 return detail::maybe_flag_fixed_fd(std::move(op), sockfd);
619}
620
624template <FdLike Fd, BufferLike Buffer>
625inline auto async_recv(Fd sockfd, detail::FixedBuffer<Buffer> buf, int flags) {
626 auto op = detail::make_op_awaiter(detail::prep_recv_fixed, sockfd,
627 buf.value.data(), buf.value.size(), flags,
628 buf.buf_index);
629 return detail::maybe_flag_fixed_fd(std::move(op), sockfd);
630}
631
635template <FdLike Fd, AnySameAs<ProvidedBufferQueue, ProvidedBufferPool> Buffer>
636inline auto async_recv(Fd sockfd, Buffer &buf, int flags) {
637 auto op = detail::make_select_buffer_op_awaiter(&buf, io_uring_prep_recv,
638 sockfd, nullptr, 0, flags);
639 return detail::maybe_flag_fixed_fd(std::move(op), sockfd);
640}
641
642#if CONDY_URING_VERSION_GE(2, 7) // >= 2.7
646template <FdLike Fd, AnySameAs<detail::BundledProvidedBufferQueue,
647 detail::BundledProvidedBufferPool>
648 Buffer>
649inline auto async_recv(Fd sockfd, Buffer &buf, int flags) {
650 auto op = detail::make_bundle_select_buffer_op_awaiter(
651 &buf, io_uring_prep_recv, sockfd, nullptr, 0, flags);
652 return detail::maybe_flag_fixed_fd(std::move(op), sockfd);
653}
654#endif
655
659template <FdLike Fd, AnySameAs<ProvidedBufferQueue, ProvidedBufferPool> Buffer,
660 typename MultiShotFunc>
661inline auto async_recv_multishot(Fd sockfd, Buffer &buf, int flags,
662 MultiShotFunc &&func) {
663 auto op = detail::make_multishot_select_buffer_op_awaiter(
664 std::forward<MultiShotFunc>(func), &buf, io_uring_prep_recv_multishot,
665 sockfd, nullptr, 0, flags);
666 return detail::maybe_flag_fixed_fd(std::move(op), sockfd);
667}
668
669#if CONDY_URING_VERSION_GE(2, 7) // >= 2.7
673template <FdLike Fd,
674 AnySameAs<detail::BundledProvidedBufferQueue,
675 detail::BundledProvidedBufferPool>
676 Buffer,
677 typename MultiShotFunc>
678inline auto async_recv_multishot(Fd sockfd, Buffer &buf, int flags,
679 MultiShotFunc &&func) {
680 auto op = detail::make_multishot_bundle_select_buffer_op_awaiter(
681 std::forward<MultiShotFunc>(func), &buf, io_uring_prep_recv_multishot,
682 sockfd, nullptr, 0, flags);
683 return detail::maybe_flag_fixed_fd(std::move(op), sockfd);
684}
685#endif
686
687#if CONDY_URING_VERSION_GE(2, 15) // >= 2.15
691template <FdLike Fd, typename MultiShotFunc>
692inline auto async_recv_multishot(Fd sockfd, ZeroCopyRxBufferPool &pool,
693 [[maybe_unused]] int flags,
694 MultiShotFunc &&func) {
695 auto zcrx_id = pool.zcrx_id();
696 auto prep_func = [=](detail::Ring *ring) {
697 auto *sqe = ring->get_sqe();
698 detail::prep_recv_zc_multishot(sqe, sockfd, zcrx_id);
699 return sqe;
700 };
702 std::move(prep_func),
704 std::forward<MultiShotFunc>(func));
705 return detail::maybe_flag_fixed_fd(std::move(op), sockfd);
706}
707#endif
708
712inline auto async_openat2(int dfd, const char *path, struct open_how *how) {
713 return detail::make_op_awaiter(io_uring_prep_openat2, dfd, path, how);
714}
715
719inline auto async_openat2_direct(int dfd, const char *path,
720 struct open_how *how, unsigned file_index) {
721 return detail::make_op_awaiter(io_uring_prep_openat2_direct, dfd, path, how,
722 file_index);
723}
724
728template <FdLike Fd> inline auto async_shutdown(Fd fd, int how) {
729 auto op = detail::make_op_awaiter(io_uring_prep_shutdown, fd, how);
730 return detail::maybe_flag_fixed_fd(std::move(op), fd);
731}
732
736inline auto async_unlinkat(int dfd, const char *path, int flags) {
737 return detail::make_op_awaiter(io_uring_prep_unlinkat, dfd, path, flags);
738}
739
743inline auto async_unlink(const char *path, int flags) {
744 return async_unlinkat(AT_FDCWD, path, flags);
745}
746
750inline auto async_renameat(int olddfd, const char *oldpath, int newdfd,
751 const char *newpath, unsigned int flags) {
752 return detail::make_op_awaiter(io_uring_prep_renameat, olddfd, oldpath,
753 newdfd, newpath, flags);
754}
755
759inline auto async_rename(const char *oldpath, const char *newpath) {
760 return async_renameat(AT_FDCWD, oldpath, AT_FDCWD, newpath, 0);
761}
762
766template <FdLike Fd>
767inline auto async_sync_file_range(Fd fd, unsigned len, __u64 offset,
768 int flags) {
769 auto op = detail::make_op_awaiter(io_uring_prep_sync_file_range, fd, len,
770 offset, flags);
771 return detail::maybe_flag_fixed_fd(std::move(op), fd);
772}
773
777inline auto async_mkdirat(int dfd, const char *path, mode_t mode) {
778 return detail::make_op_awaiter(io_uring_prep_mkdirat, dfd, path, mode);
779}
780
784inline auto async_mkdir(const char *path, mode_t mode) {
785 return async_mkdirat(AT_FDCWD, path, mode);
786}
787
791inline auto async_symlinkat(const char *target, int newdirfd,
792 const char *linkpath) {
793 return detail::make_op_awaiter(io_uring_prep_symlinkat, target, newdirfd,
794 linkpath);
795}
796
800inline auto async_symlink(const char *target, const char *linkpath) {
801 return async_symlinkat(target, AT_FDCWD, linkpath);
802}
803
807inline auto async_linkat(int olddfd, const char *oldpath, int newdfd,
808 const char *newpath, int flags) {
809 return detail::make_op_awaiter(io_uring_prep_linkat, olddfd, oldpath,
810 newdfd, newpath, flags);
811}
812
816inline auto async_link(const char *oldpath, const char *newpath, int flags) {
817 return async_linkat(AT_FDCWD, oldpath, AT_FDCWD, newpath, flags);
818}
819
823inline auto async_getxattr(const char *name, char *value, const char *path,
824 unsigned int len) {
825 return detail::make_op_awaiter(io_uring_prep_getxattr, name, value, path,
826 len);
827}
828
832inline auto async_setxattr(const char *name, const char *value,
833 const char *path, int flags, unsigned int len) {
834 return detail::make_op_awaiter(io_uring_prep_setxattr, name, value, path,
835 flags, len);
836}
837
841inline auto async_fgetxattr(int fd, const char *name, char *value,
842 unsigned int len) {
843 return detail::make_op_awaiter(io_uring_prep_fgetxattr, fd, name, value,
844 len);
845}
846
850inline auto async_fsetxattr(int fd, const char *name, const char *value,
851 int flags, unsigned int len) {
852 return detail::make_op_awaiter(io_uring_prep_fsetxattr, fd, name, value,
853 flags, len);
854}
855
859inline auto async_socket(int domain, int type, int protocol,
860 unsigned int flags) {
861 return detail::make_op_awaiter(io_uring_prep_socket, domain, type, protocol,
862 flags);
863}
864
868inline auto async_socket_direct(int domain, int type, int protocol,
869 unsigned file_index, unsigned int flags) {
870 return detail::make_op_awaiter(io_uring_prep_socket_direct, domain, type,
871 protocol, file_index, flags);
872}
873
882template <CQEHandlerLike CQEHandler = SimpleCQEHandler, FdLike Fd,
883 typename CmdFunc, typename... Args>
884[[deprecated]] inline auto
885async_uring_cmd(int cmd_op, Fd fd, CmdFunc &&cmd_func, Args &&...handler_args) {
886 return async_uring_cmd(cmd_op, fd, std::forward<CmdFunc>(cmd_func),
887 CQEHandler(std::forward<Args>(handler_args)...));
888}
889
896template <FdLike Fd, typename CmdFunc, CQEHandlerLike CQEHandler>
897inline auto async_uring_cmd(int cmd_op, Fd fd, CmdFunc &&cmd_func,
898 CQEHandler &&cqe_handler) {
899 auto prep_func = [cmd_op, fd = detail::unwrap_fixed(fd),
900 cmd_func =
901 std::forward<CmdFunc>(cmd_func)](detail::Ring *ring) {
902 auto *sqe = ring->get_sqe();
903 io_uring_prep_uring_cmd(sqe, cmd_op, fd);
904 cmd_func(sqe);
905 return sqe;
906 };
907 auto op = build_op_awaiter(std::move(prep_func),
908 std::forward<CQEHandler>(cqe_handler));
909 return detail::maybe_flag_fixed_fd(std::move(op), fd);
910}
911
921template <CQEHandlerLike CQEHandler = SimpleCQEHandler, FdLike Fd,
922 typename CmdFunc, typename MultiShotFunc, typename... Args>
923[[deprecated]] inline auto
924async_uring_cmd_multishot(int cmd_op, Fd fd, CmdFunc &&cmd_func,
925 MultiShotFunc &&func, Args &&...handler_args) {
927 cmd_op, fd, std::forward<CmdFunc>(cmd_func),
928 CQEHandler(std::forward<Args>(handler_args)...),
929 std::forward<MultiShotFunc>(func));
930}
931
939template <FdLike Fd, typename CmdFunc, CQEHandlerLike CQEHandler,
940 typename MultiShotFunc>
941inline auto async_uring_cmd_multishot(int cmd_op, Fd fd, CmdFunc &&cmd_func,
942 CQEHandler &&cqe_handler,
943 MultiShotFunc &&func) {
944 auto prep_func = [cmd_op, fd = detail::unwrap_fixed(fd),
945 cmd_func =
946 std::forward<CmdFunc>(cmd_func)](detail::Ring *ring) {
947 auto *sqe = ring->get_sqe();
948 io_uring_prep_uring_cmd(sqe, cmd_op, fd);
949 cmd_func(sqe);
950 return sqe;
951 };
952 auto op = build_multishot_op_awaiter(std::move(prep_func),
953 std::forward<CQEHandler>(cqe_handler),
954 std::forward<MultiShotFunc>(func));
955 return detail::maybe_flag_fixed_fd(std::move(op), fd);
956}
957
958#if CONDY_URING_VERSION_GE(2, 13) // >= 2.13
967template <CQEHandlerLike CQEHandler = SimpleCQEHandler, FdLike Fd,
968 typename CmdFunc, typename... Args>
969[[deprecated]] inline auto async_uring_cmd128(int cmd_op, Fd fd,
970 CmdFunc &&cmd_func,
971 Args &&...handler_args) {
972 return async_uring_cmd128(cmd_op, fd, std::forward<CmdFunc>(cmd_func),
973 CQEHandler(std::forward<Args>(handler_args)...));
974}
975
982template <FdLike Fd, typename CmdFunc, CQEHandlerLike CQEHandler>
983inline auto async_uring_cmd128(int cmd_op, Fd fd, CmdFunc &&cmd_func,
984 CQEHandler &&cqe_handler) {
985 auto prep_func = [cmd_op, fd = detail::unwrap_fixed(fd),
986 cmd_func =
987 std::forward<CmdFunc>(cmd_func)](detail::Ring *ring) {
988 auto *sqe = ring->get_sqe128();
989 if (sqe) {
990 io_uring_prep_uring_cmd128(sqe, cmd_op, fd);
991 cmd_func(sqe);
992 }
993 return sqe;
994 };
995 auto op = build_op_awaiter(std::move(prep_func),
996 std::forward<CQEHandler>(cqe_handler));
997 return detail::maybe_flag_fixed_fd(std::move(op), fd);
998}
999#endif
1000
1001#if CONDY_URING_VERSION_GE(2, 5) // >= 2.5
1005template <FdLike Fd>
1006inline auto async_cmd_sock(int cmd_op, Fd fd, int level, int optname,
1007 void *optval, int optlen) {
1008 auto op = detail::make_op_awaiter(io_uring_prep_cmd_sock, cmd_op, fd, level,
1009 optname, optval, optlen);
1010 return detail::maybe_flag_fixed_fd(std::move(op), fd);
1011}
1012#endif
1013
1014#if CONDY_URING_VERSION_GE(2, 13) // >= 2.13
1018template <FdLike Fd>
1019inline auto async_cmd_getsockname(Fd fd, struct sockaddr *sockaddr,
1020 socklen_t *sockaddr_len, int peer) {
1021 auto op = detail::make_op_awaiter(io_uring_prep_cmd_getsockname, fd,
1022 sockaddr, sockaddr_len, peer);
1023 return detail::maybe_flag_fixed_fd(std::move(op), fd);
1024}
1025#endif
1026
1027#if CONDY_URING_VERSION_GE(2, 6) // >= 2.6
1031inline auto async_waitid(idtype_t idtype, id_t id, siginfo_t *infop,
1032 int options, unsigned int flags) {
1033 return detail::make_op_awaiter(io_uring_prep_waitid, idtype, id, infop,
1034 options, flags);
1035}
1036#endif
1037
1038#if CONDY_URING_VERSION_GE(2, 6) // >= 2.6
1042inline auto async_futex_wake(uint32_t *futex, uint64_t val, uint64_t mask,
1043 uint32_t futex_flags, unsigned int flags) {
1044 return detail::make_op_awaiter(io_uring_prep_futex_wake, futex, val, mask,
1045 futex_flags, flags);
1046}
1047#endif
1048
1049#if CONDY_URING_VERSION_GE(2, 6) // >= 2.6
1053inline auto async_futex_wait(uint32_t *futex, uint64_t val, uint64_t mask,
1054 uint32_t futex_flags, unsigned int flags) {
1055 return detail::make_op_awaiter(io_uring_prep_futex_wait, futex, val, mask,
1056 futex_flags, flags);
1057}
1058#endif
1059
1060#if CONDY_URING_VERSION_GE(2, 6) // >= 2.6
1064inline auto async_futex_waitv(struct futex_waitv *futex, uint32_t nr_futex,
1065 unsigned int flags) {
1066 return detail::make_op_awaiter(io_uring_prep_futex_waitv, futex, nr_futex,
1067 flags);
1068}
1069#endif
1070
1071#if CONDY_URING_VERSION_GE(2, 6) // >= 2.6
1075inline auto async_fixed_fd_install(int fixed_fd, unsigned int flags) {
1076 return detail::make_op_awaiter(io_uring_prep_fixed_fd_install, fixed_fd,
1077 flags);
1078}
1079#endif
1080
1081#if CONDY_URING_VERSION_GE(2, 6) // >= 2.6
1085template <FdLike Fd> inline auto async_ftruncate(Fd fd, loff_t len) {
1086 auto op = detail::make_op_awaiter(io_uring_prep_ftruncate, fd, len);
1087 return detail::maybe_flag_fixed_fd(std::move(op), fd);
1088}
1089#endif
1090
1091#if CONDY_URING_VERSION_GE(2, 8) // >= 2.8
1095template <FdLike Fd>
1096inline auto async_cmd_discard(Fd fd, uint64_t offset, uint64_t nbytes) {
1097 auto op =
1098 detail::make_op_awaiter(io_uring_prep_cmd_discard, fd, offset, nbytes);
1099 return detail::maybe_flag_fixed_fd(std::move(op), fd);
1100}
1101#endif
1102
1103#if CONDY_URING_VERSION_GE(2, 7) // >= 2.7
1107template <FdLike Fd>
1108inline auto async_bind(Fd fd, struct sockaddr *addr, socklen_t addrlen) {
1109 auto op = detail::make_op_awaiter(io_uring_prep_bind, fd, addr, addrlen);
1110 return detail::maybe_flag_fixed_fd(std::move(op), fd);
1111}
1112#endif
1113
1114#if CONDY_URING_VERSION_GE(2, 7) // >= 2.7
1118template <FdLike Fd> inline auto async_listen(Fd fd, int backlog) {
1119 auto op = detail::make_op_awaiter(io_uring_prep_listen, fd, backlog);
1120 return detail::maybe_flag_fixed_fd(std::move(op), fd);
1121}
1122#endif
1123
1127inline auto async_epoll_ctl(int epfd, int fd, int op, struct epoll_event *ev) {
1128 return detail::make_op_awaiter(io_uring_prep_epoll_ctl, epfd, fd, op, ev);
1129}
1130
1131#if CONDY_URING_VERSION_GE(2, 10) // >= 2.10
1135inline auto async_epoll_wait(int fd, struct epoll_event *events, int maxevents,
1136 unsigned flags) {
1137 return detail::make_op_awaiter(io_uring_prep_epoll_wait, fd, events,
1138 maxevents, flags);
1139}
1140#endif
1141
1142#if CONDY_URING_VERSION_GE(2, 12) // >= 2.12
1146inline auto async_pipe(int *fds, int pipe_flags) {
1147 return detail::make_op_awaiter(io_uring_prep_pipe, fds, pipe_flags);
1148}
1149#endif
1150
1151#if CONDY_URING_VERSION_GE(2, 12) // >= 2.12
1155inline auto async_pipe_direct(int *fds, int pipe_flags,
1156 unsigned int file_index) {
1157 return detail::make_op_awaiter(io_uring_prep_pipe_direct, fds, pipe_flags,
1158 file_index);
1159}
1160#endif
1161
1162} // namespace condy
Helper functions for composing asynchronous operations.
A CQE handler that returns the selected buffers based on the result of the CQE.
Definitions of asynchronous operations.
Helper functions for asynchronous operations.
The main namespace for the Condy library.
Definition condy.hpp:38
auto async_symlinkat(const char *target, int newdirfd, const char *linkpath)
See io_uring_prep_symlinkat.
auto async_splice(Fd1 fd_in, int64_t off_in, Fd2 fd_out, int64_t off_out, unsigned int nbytes, unsigned int splice_flags)
See io_uring_prep_splice.
auto async_read(Fd fd, const Buffer &buf, __u64 offset, int flags=0)
See io_uring_prep_read.
auto async_sendto(Fd sockfd, const Buffer &buf, int flags, const struct sockaddr *addr, socklen_t addrlen)
See io_uring_prep_send and io_uring_prep_send_set_addr.
auto async_fsetxattr(int fd, const char *name, const char *value, int flags, unsigned int len)
See io_uring_prep_fsetxattr.
auto async_fadvise(Fd fd, __u64 offset, off_t len, int advice)
See io_uring_prep_fadvise.
auto async_writev(Fd fd, const struct iovec *iovecs, unsigned int nr_vecs, __u64 offset, int flags)
See io_uring_prep_writev2.
auto async_socket_direct(int domain, int type, int protocol, unsigned file_index, unsigned int flags)
See io_uring_prep_socket_direct.
auto async_fsync(Fd fd, unsigned fsync_flags)
See io_uring_prep_fsync.
auto async_recvmsg(Fd fd, struct msghdr *msg, unsigned flags)
See io_uring_prep_recvmsg.
auto async_openat2(int dfd, const char *path, struct open_how *how)
See io_uring_prep_openat2.
auto async_open_direct(const char *path, int flags, mode_t mode, unsigned file_index)
See io_uring_prep_openat_direct.
auto async_getxattr(const char *name, char *value, const char *path, unsigned int len)
See io_uring_prep_getxattr.
auto async_unlinkat(int dfd, const char *path, int flags)
See io_uring_prep_unlinkat.
auto async_openat_direct(int dfd, const char *path, int flags, mode_t mode, unsigned file_index)
See io_uring_prep_openat_direct.
auto async_epoll_ctl(int epfd, int fd, int op, struct epoll_event *ev)
See io_uring_prep_epoll_ctl.
auto async_mkdir(const char *path, mode_t mode)
See io_uring_prep_mkdirat.
auto async_fgetxattr(int fd, const char *name, char *value, unsigned int len)
See io_uring_prep_fgetxattr.
auto async_statx(int dfd, const char *path, int flags, unsigned mask, struct statx *statxbuf)
See io_uring_prep_statx.
auto async_send_zc(Fd sockfd, const Buffer &buf, int flags, unsigned zc_flags, FreeFunc &&func)
See io_uring_prep_send_zc.
auto async_link(const char *oldpath, const char *newpath, int flags)
See io_uring_prep_linkat.
auto async_multishot_accept_direct(Fd fd, struct sockaddr *addr, socklen_t *addrlen, int flags, MultiShotFunc &&func)
See io_uring_prep_multishot_accept_direct.
auto async_recv_multishot(Fd sockfd, Buffer &buf, int flags, MultiShotFunc &&func)
See io_uring_prep_recv_multishot.
auto async_multishot_accept(Fd fd, struct sockaddr *addr, socklen_t *addrlen, int flags, MultiShotFunc &&func)
See io_uring_prep_multishot_accept.
auto async_fallocate(Fd fd, int mode, __u64 offset, __u64 len)
See io_uring_prep_fallocate.
auto async_madvise(void *addr, __u32 length, int advice)
See io_uring_prep_madvise.
auto async_symlink(const char *target, const char *linkpath)
See io_uring_prep_symlinkat.
auto async_sync_file_range(Fd fd, unsigned len, __u64 offset, int flags)
See io_uring_prep_sync_file_range.
auto async_connect(Fd fd, const struct sockaddr *addr, socklen_t addrlen)
See io_uring_prep_connect.
auto async_files_update(int *fds, unsigned nr_fds, int offset)
See io_uring_prep_files_update.
auto build_op_awaiter(PrepFunc &&func, CQEHandler &&cqe_handler)
Build a single-shot operation awaiter with custom CQE handler.
auto async_tee(Fd1 fd_in, Fd2 fd_out, unsigned int nbytes, unsigned int splice_flags)
See io_uring_prep_tee.
auto async_send(Fd sockfd, const Buffer &buf, int flags)
See io_uring_prep_send.
auto async_recvmsg_multishot(Fd fd, struct msghdr *msg, unsigned flags, Buffer &buf, MultiShotFunc &&func)
See io_uring_prep_recvmsg_multishot.
auto async_write(Fd fd, const Buffer &buf, __u64 offset, int flags=0)
See io_uring_prep_write.
auto async_sendmsg(Fd fd, const struct msghdr *msg, unsigned flags)
See io_uring_prep_sendmsg.
auto async_cancel_fd(Fd fd, unsigned int flags)
See io_uring_prep_cancel_fd.
auto async_recv(Fd sockfd, const Buffer &buf, int flags)
See io_uring_prep_recv.
auto async_link_timeout(struct __kernel_timespec *ts, unsigned flags)
See io_uring_prep_link_timeout.
auto async_nop()
See io_uring_prep_nop.
auto async_sendmsg_zc(Fd fd, const struct msghdr *msg, unsigned flags, FreeFunc &&func)
See io_uring_prep_sendmsg_zc.
auto async_close(int fd)
See io_uring_prep_close.
auto async_uring_cmd_multishot(int cmd_op, Fd fd, CmdFunc &&cmd_func, MultiShotFunc &&func, Args &&...handler_args)
See io_uring_prep_uring_cmd.
auto async_sendto_zc(Fd sockfd, const Buffer &buf, int flags, const struct sockaddr *addr, socklen_t addrlen, unsigned zc_flags, FreeFunc &&func)
See io_uring_prep_send_zc and io_uring_prep_send_set_addr.
auto async_open(const char *path, int flags, mode_t mode)
See io_uring_prep_openat.
auto async_renameat(int olddfd, const char *oldpath, int newdfd, const char *newpath, unsigned int flags)
See io_uring_prep_renameat.
auto async_accept_direct(Fd fd, struct sockaddr *addr, socklen_t *addrlen, int flags, unsigned int file_index)
See io_uring_prep_accept_direct.
auto async_timeout(struct __kernel_timespec *ts, unsigned count, unsigned flags)
See io_uring_prep_timeout.
auto async_rename(const char *oldpath, const char *newpath)
See io_uring_prep_renameat.
auto async_setxattr(const char *name, const char *value, const char *path, int flags, unsigned int len)
See io_uring_prep_setxattr.
auto async_openat2_direct(int dfd, const char *path, struct open_how *how, unsigned file_index)
See io_uring_prep_openat2_direct.
auto async_unlink(const char *path, int flags)
See io_uring_prep_unlinkat.
auto async_accept(Fd fd, struct sockaddr *addr, socklen_t *addrlen, int flags)
See io_uring_prep_accept.
auto async_mkdirat(int dfd, const char *path, mode_t mode)
See io_uring_prep_mkdirat.
auto build_multishot_op_awaiter(PrepFunc &&func, CQEHandler &&cqe_handler, MultiShotFunc &&multishot_func)
Build a multi-shot operation awaiter with custom CQE handler.
auto async_readv(Fd fd, const struct iovec *iovecs, unsigned nr_vecs, __u64 offset, int flags)
See io_uring_prep_readv2.
auto async_openat(int dfd, const char *path, int flags, mode_t mode)
See io_uring_prep_openat.
auto async_linkat(int olddfd, const char *oldpath, int newdfd, const char *newpath, int flags)
See io_uring_prep_linkat.
auto async_uring_cmd(int cmd_op, Fd fd, CmdFunc &&cmd_func, Args &&...handler_args)
See io_uring_prep_uring_cmd.
auto async_shutdown(Fd fd, int how)
See io_uring_prep_shutdown.
auto async_socket(int domain, int type, int protocol, unsigned int flags)
See io_uring_prep_socket.
Support for io_uring zero-copy receive (zcrx) buffers.