Condy v1.8
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 !IO_URING_CHECK_VERSION(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 !IO_URING_CHECK_VERSION(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 !IO_URING_CHECK_VERSION(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 !IO_URING_CHECK_VERSION(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 !IO_URING_CHECK_VERSION(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) {
354 auto op = detail::make_op_awaiter(io_uring_prep_read, fd, buf.data(),
355 buf.size(), offset);
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 auto op =
365 detail::make_op_awaiter(io_uring_prep_read_fixed, fd, buf.value.data(),
366 buf.value.size(), offset, buf.buf_index);
367 return detail::maybe_flag_fixed_fd(std::move(op), fd);
368}
369
373template <FdLike Fd, AnySameAs<ProvidedBufferQueue, ProvidedBufferPool> Buffer>
374inline auto async_read(Fd fd, Buffer &buf, __u64 offset) {
375 auto op = detail::make_select_buffer_op_awaiter(&buf, io_uring_prep_read,
376 fd, nullptr, 0, offset);
377 return detail::maybe_flag_fixed_fd(std::move(op), fd);
378}
379
380#if !IO_URING_CHECK_VERSION(2, 6) // >= 2.6
384template <FdLike Fd, AnySameAs<ProvidedBufferQueue, ProvidedBufferPool> Buffer,
385 typename MultiShotFunc>
386inline auto async_read_multishot(Fd fd, Buffer &buf, __u64 offset,
387 MultiShotFunc &&func) {
388 auto op = detail::make_multishot_select_buffer_op_awaiter(
389 std::forward<MultiShotFunc>(func), &buf, io_uring_prep_read_multishot,
390 fd, 0, offset, buf.bgid());
391 return detail::maybe_flag_fixed_fd(std::move(op), fd);
392}
393#endif
394
398template <FdLike Fd, BufferLike Buffer>
399inline auto async_write(Fd fd, const Buffer &buf, __u64 offset) {
400 auto op = detail::make_op_awaiter(io_uring_prep_write, fd, buf.data(),
401 buf.size(), offset);
402 return detail::maybe_flag_fixed_fd(std::move(op), fd);
403}
404
408template <FdLike Fd, BufferLike Buffer>
409inline auto async_write(Fd fd, detail::FixedBuffer<Buffer> buf, __u64 offset) {
410 auto op =
411 detail::make_op_awaiter(io_uring_prep_write_fixed, fd, buf.value.data(),
412 buf.value.size(), offset, buf.buf_index);
413 return detail::maybe_flag_fixed_fd(std::move(op), fd);
414}
415
419inline auto async_statx(int dfd, const char *path, int flags, unsigned mask,
420 struct statx *statxbuf) {
421 return detail::make_op_awaiter(io_uring_prep_statx, dfd, path, flags, mask,
422 statxbuf);
423}
424
428template <FdLike Fd>
429inline auto async_fadvise(Fd fd, __u64 offset, off_t len, int advice) {
430 auto op =
431 detail::make_op_awaiter(io_uring_prep_fadvise, fd, offset, len, advice);
432 return detail::maybe_flag_fixed_fd(std::move(op), fd);
433}
434
435#if !IO_URING_CHECK_VERSION(2, 7) // >= 2.7
439template <FdLike Fd>
440inline auto async_fadvise64(Fd fd, __u64 offset, off_t len, int advice) {
441 auto op = detail::make_op_awaiter(io_uring_prep_fadvise64, fd, offset, len,
442 advice);
443 return detail::maybe_flag_fixed_fd(std::move(op), fd);
444}
445#endif
446
450inline auto async_madvise(void *addr, __u32 length, int advice) {
451 return detail::make_op_awaiter(io_uring_prep_madvise, addr, length, advice);
452}
453
454#if !IO_URING_CHECK_VERSION(2, 7) // >= 2.7
458inline auto async_madvise64(void *addr, off_t length, int advice) {
459 auto op =
460 detail::make_op_awaiter(io_uring_prep_madvise64, addr, length, advice);
461 return op;
462}
463#endif
464
468template <FdLike Fd, BufferLike Buffer>
469inline auto async_send(Fd sockfd, const Buffer &buf, int flags) {
470 auto op = detail::make_op_awaiter(io_uring_prep_send, sockfd, buf.data(),
471 buf.size(), flags);
472 return detail::maybe_flag_fixed_fd(std::move(op), sockfd);
473}
474
478template <FdLike Fd>
479inline auto async_send(Fd sockfd, ProvidedBufferQueue &buf, int flags) {
480 auto op = detail::make_select_buffer_op_awaiter(&buf, io_uring_prep_send,
481 sockfd, nullptr, 0, flags);
482 return detail::maybe_flag_fixed_fd(std::move(op), sockfd);
483}
484
485#if !IO_URING_CHECK_VERSION(2, 7) // >= 2.7
489template <FdLike Fd>
490inline auto async_send(Fd sockfd, detail::BundledProvidedBufferQueue &buf,
491 int flags) {
492 auto op = detail::make_bundle_select_buffer_op_awaiter(
493 &buf, io_uring_prep_send, sockfd, nullptr, 0, flags);
494 return detail::maybe_flag_fixed_fd(std::move(op), sockfd);
495}
496#endif
497
501template <FdLike Fd, BufferLike Buffer>
502inline auto async_sendto(Fd sockfd, const Buffer &buf, int flags,
503 const struct sockaddr *addr, socklen_t addrlen) {
504 auto op = detail::make_op_awaiter(detail::prep_sendto, sockfd, buf.data(),
505 buf.size(), flags, addr, addrlen);
506 return detail::maybe_flag_fixed_fd(std::move(op), sockfd);
507}
508
512template <FdLike Fd>
513inline auto async_sendto(Fd sockfd, ProvidedBufferQueue &buf, int flags,
514 const struct sockaddr *addr, socklen_t addrlen) {
515 auto op = detail::make_select_buffer_op_awaiter(
516 &buf, detail::prep_sendto, sockfd, nullptr, 0, flags, addr, addrlen);
517 return detail::maybe_flag_fixed_fd(std::move(op), sockfd);
518}
519
520#if !IO_URING_CHECK_VERSION(2, 7) // >= 2.7
524template <FdLike Fd>
525inline auto async_sendto(Fd sockfd, detail::BundledProvidedBufferQueue &buf,
526 int flags, const struct sockaddr *addr,
527 socklen_t addrlen) {
528 auto op = detail::make_bundle_select_buffer_op_awaiter(
529 &buf, detail::prep_sendto, sockfd, nullptr, 0, flags, addr, addrlen);
530 return detail::maybe_flag_fixed_fd(std::move(op), sockfd);
531}
532#endif
533
537template <FdLike Fd, typename Buffer, typename FreeFunc>
538inline auto async_send_zc(Fd sockfd, const Buffer &buf, int flags,
539 unsigned zc_flags, FreeFunc &&func) {
540 auto op = detail::make_zero_copy_op_awaiter(
541 std::forward<FreeFunc>(func), io_uring_prep_send_zc, sockfd, buf.data(),
542 buf.size(), flags, zc_flags);
543 return detail::maybe_flag_fixed_fd(std::move(op), sockfd);
544}
545
549template <FdLike Fd, BufferLike Buffer, typename FreeFunc>
550inline auto async_send_zc(Fd sockfd, detail::FixedBuffer<Buffer> buf, int flags,
551 unsigned zc_flags, FreeFunc &&func) {
552 auto op = detail::make_zero_copy_op_awaiter(
553 std::forward<FreeFunc>(func), io_uring_prep_send_zc_fixed, sockfd,
554 buf.value.data(), buf.value.size(), flags, zc_flags, buf.buf_index);
555 return detail::maybe_flag_fixed_fd(std::move(op), sockfd);
556}
557
561template <FdLike Fd, BufferLike Buffer, typename FreeFunc>
562inline auto async_sendto_zc(Fd sockfd, const Buffer &buf, int flags,
563 const struct sockaddr *addr, socklen_t addrlen,
564 unsigned zc_flags, FreeFunc &&func) {
565 auto op = detail::make_zero_copy_op_awaiter(
566 std::forward<FreeFunc>(func), detail::prep_sendto_zc, sockfd,
567 buf.data(), buf.size(), flags, addr, addrlen, 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_sendto_zc(Fd sockfd, detail::FixedBuffer<Buffer> buf,
576 int flags, const struct sockaddr *addr,
577 socklen_t addrlen, unsigned zc_flags,
578 FreeFunc &&func) {
579 auto op = detail::make_zero_copy_op_awaiter(
580 std::forward<FreeFunc>(func), detail::prep_sendto_zc_fixed, sockfd,
581 buf.value.data(), buf.value.size(), flags, addr, addrlen, zc_flags,
582 buf.buf_index);
583 return detail::maybe_flag_fixed_fd(std::move(op), sockfd);
584}
585
589template <FdLike Fd, BufferLike Buffer>
590inline auto async_recv(Fd sockfd, const Buffer &buf, int flags) {
591 auto op = detail::make_op_awaiter(io_uring_prep_recv, sockfd, buf.data(),
592 buf.size(), flags);
593 return detail::maybe_flag_fixed_fd(std::move(op), sockfd);
594}
595
599template <FdLike Fd, AnySameAs<ProvidedBufferQueue, ProvidedBufferPool> Buffer>
600inline auto async_recv(Fd sockfd, Buffer &buf, int flags) {
601 auto op = detail::make_select_buffer_op_awaiter(&buf, io_uring_prep_recv,
602 sockfd, nullptr, 0, flags);
603 return detail::maybe_flag_fixed_fd(std::move(op), sockfd);
604}
605
606#if !IO_URING_CHECK_VERSION(2, 7) // >= 2.7
610template <FdLike Fd, AnySameAs<detail::BundledProvidedBufferQueue,
611 detail::BundledProvidedBufferPool>
612 Buffer>
613inline auto async_recv(Fd sockfd, Buffer &buf, int flags) {
614 auto op = detail::make_bundle_select_buffer_op_awaiter(
615 &buf, io_uring_prep_recv, sockfd, nullptr, 0, flags);
616 return detail::maybe_flag_fixed_fd(std::move(op), sockfd);
617}
618#endif
619
623template <FdLike Fd, AnySameAs<ProvidedBufferQueue, ProvidedBufferPool> Buffer,
624 typename MultiShotFunc>
625inline auto async_recv_multishot(Fd sockfd, Buffer &buf, int flags,
626 MultiShotFunc &&func) {
627 auto op = detail::make_multishot_select_buffer_op_awaiter(
628 std::forward<MultiShotFunc>(func), &buf, io_uring_prep_recv_multishot,
629 sockfd, nullptr, 0, flags);
630 return detail::maybe_flag_fixed_fd(std::move(op), sockfd);
631}
632
633#if !IO_URING_CHECK_VERSION(2, 7) // >= 2.7
637template <FdLike Fd,
638 AnySameAs<detail::BundledProvidedBufferQueue,
639 detail::BundledProvidedBufferPool>
640 Buffer,
641 typename MultiShotFunc>
642inline auto async_recv_multishot(Fd sockfd, Buffer &buf, int flags,
643 MultiShotFunc &&func) {
644 auto op = detail::make_multishot_bundle_select_buffer_op_awaiter(
645 std::forward<MultiShotFunc>(func), &buf, io_uring_prep_recv_multishot,
646 sockfd, nullptr, 0, flags);
647 return detail::maybe_flag_fixed_fd(std::move(op), sockfd);
648}
649#endif
650
651#if !IO_URING_CHECK_VERSION(2, 15) // >= 2.15
655template <FdLike Fd, typename MultiShotFunc>
656inline auto async_recv_multishot(Fd sockfd, ZeroCopyRxBufferPool &pool,
657 [[maybe_unused]] int flags,
658 MultiShotFunc &&func) {
659 auto zcrx_id = pool.zcrx_id();
660 auto prep_func = [=](detail::Ring *ring) {
661 auto *sqe = ring->get_sqe();
662 detail::prep_recv_zc_multishot(sqe, sockfd, zcrx_id);
663 return sqe;
664 };
667 std::move(prep_func), std::forward<MultiShotFunc>(func), &pool);
668 return detail::maybe_flag_fixed_fd(std::move(op), sockfd);
669}
670#endif
671
675inline auto async_openat2(int dfd, const char *path, struct open_how *how) {
676 return detail::make_op_awaiter(io_uring_prep_openat2, dfd, path, how);
677}
678
682inline auto async_openat2_direct(int dfd, const char *path,
683 struct open_how *how, unsigned file_index) {
684 return detail::make_op_awaiter(io_uring_prep_openat2_direct, dfd, path, how,
685 file_index);
686}
687
691template <FdLike Fd> inline auto async_shutdown(Fd fd, int how) {
692 auto op = detail::make_op_awaiter(io_uring_prep_shutdown, fd, how);
693 return detail::maybe_flag_fixed_fd(std::move(op), fd);
694}
695
699inline auto async_unlinkat(int dfd, const char *path, int flags) {
700 return detail::make_op_awaiter(io_uring_prep_unlinkat, dfd, path, flags);
701}
702
706inline auto async_unlink(const char *path, int flags) {
707 return async_unlinkat(AT_FDCWD, path, flags);
708}
709
713inline auto async_renameat(int olddfd, const char *oldpath, int newdfd,
714 const char *newpath, unsigned int flags) {
715 return detail::make_op_awaiter(io_uring_prep_renameat, olddfd, oldpath,
716 newdfd, newpath, flags);
717}
718
722inline auto async_rename(const char *oldpath, const char *newpath) {
723 return async_renameat(AT_FDCWD, oldpath, AT_FDCWD, newpath, 0);
724}
725
729template <FdLike Fd>
730inline auto async_sync_file_range(Fd fd, unsigned len, __u64 offset,
731 int flags) {
732 auto op = detail::make_op_awaiter(io_uring_prep_sync_file_range, fd, len,
733 offset, flags);
734 return detail::maybe_flag_fixed_fd(std::move(op), fd);
735}
736
740inline auto async_mkdirat(int dfd, const char *path, mode_t mode) {
741 return detail::make_op_awaiter(io_uring_prep_mkdirat, dfd, path, mode);
742}
743
747inline auto async_mkdir(const char *path, mode_t mode) {
748 return async_mkdirat(AT_FDCWD, path, mode);
749}
750
754inline auto async_symlinkat(const char *target, int newdirfd,
755 const char *linkpath) {
756 return detail::make_op_awaiter(io_uring_prep_symlinkat, target, newdirfd,
757 linkpath);
758}
759
763inline auto async_symlink(const char *target, const char *linkpath) {
764 return async_symlinkat(target, AT_FDCWD, linkpath);
765}
766
770inline auto async_linkat(int olddfd, const char *oldpath, int newdfd,
771 const char *newpath, int flags) {
772 return detail::make_op_awaiter(io_uring_prep_linkat, olddfd, oldpath,
773 newdfd, newpath, flags);
774}
775
779inline auto async_link(const char *oldpath, const char *newpath, int flags) {
780 return async_linkat(AT_FDCWD, oldpath, AT_FDCWD, newpath, flags);
781}
782
786inline auto async_getxattr(const char *name, char *value, const char *path,
787 unsigned int len) {
788 return detail::make_op_awaiter(io_uring_prep_getxattr, name, value, path,
789 len);
790}
791
795inline auto async_setxattr(const char *name, const char *value,
796 const char *path, int flags, unsigned int len) {
797 return detail::make_op_awaiter(io_uring_prep_setxattr, name, value, path,
798 flags, len);
799}
800
804inline auto async_fgetxattr(int fd, const char *name, char *value,
805 unsigned int len) {
806 return detail::make_op_awaiter(io_uring_prep_fgetxattr, fd, name, value,
807 len);
808}
809
813inline auto async_fsetxattr(int fd, const char *name, const char *value,
814 int flags, unsigned int len) {
815 return detail::make_op_awaiter(io_uring_prep_fsetxattr, fd, name, value,
816 flags, len);
817}
818
822inline auto async_socket(int domain, int type, int protocol,
823 unsigned int flags) {
824 return detail::make_op_awaiter(io_uring_prep_socket, domain, type, protocol,
825 flags);
826}
827
831inline auto async_socket_direct(int domain, int type, int protocol,
832 unsigned file_index, unsigned int flags) {
833 return detail::make_op_awaiter(io_uring_prep_socket_direct, domain, type,
834 protocol, file_index, flags);
835}
836
843template <CQEHandlerLike CQEHandler = SimpleCQEHandler, FdLike Fd,
844 typename CmdFunc>
845inline auto async_uring_cmd(int cmd_op, Fd fd, CmdFunc &&cmd_func) {
846 auto prep_func = [cmd_op, fd, cmd_func = std::forward<CmdFunc>(cmd_func)](
847 detail::Ring *ring) {
848 auto *sqe = ring->get_sqe();
849 io_uring_prep_uring_cmd(sqe, cmd_op, fd);
850 cmd_func(sqe);
851 return sqe;
852 };
853 auto op = build_op_awaiter<CQEHandler>(std::move(prep_func));
854 return detail::maybe_flag_fixed_fd(std::move(op), fd);
855}
856
860template <CQEHandlerLike CQEHandler = SimpleCQEHandler, FdLike Fd,
861 typename CmdFunc, typename MultiShotFunc>
862inline auto async_uring_cmd_multishot(int cmd_op, Fd fd, CmdFunc &&cmd_func,
863 MultiShotFunc &&func) {
864 auto prep_func = [cmd_op, fd, cmd_func = std::forward<CmdFunc>(cmd_func)](
865 detail::Ring *ring) {
866 auto *sqe = ring->get_sqe();
867 io_uring_prep_uring_cmd(sqe, cmd_op, fd);
868 cmd_func(sqe);
869 return sqe;
870 };
872 std::move(prep_func), std::forward<MultiShotFunc>(func));
873 return detail::maybe_flag_fixed_fd(std::move(op), fd);
874}
875
876#if !IO_URING_CHECK_VERSION(2, 13) // >= 2.13
883template <CQEHandlerLike CQEHandler = SimpleCQEHandler, FdLike Fd,
884 typename CmdFunc>
885inline auto async_uring_cmd128(int cmd_op, Fd fd, CmdFunc &&cmd_func) {
886 auto prep_func = [cmd_op, fd, cmd_func = std::forward<CmdFunc>(cmd_func)](
887 detail::Ring *ring) {
888 auto *sqe = ring->get_sqe128();
889 if (!sqe) {
890 detail::panic_on("SQE128 not enabled in the ring");
891 }
892 io_uring_prep_uring_cmd128(sqe, cmd_op, fd);
893 cmd_func(sqe);
894 return sqe;
895 };
896 auto op = build_op_awaiter<CQEHandler>(std::move(prep_func));
897 return detail::maybe_flag_fixed_fd(std::move(op), fd);
898}
899#endif
900
901#if !IO_URING_CHECK_VERSION(2, 5) // >= 2.5
905template <FdLike Fd>
906inline auto async_cmd_sock(int cmd_op, Fd fd, int level, int optname,
907 void *optval, int optlen) {
908 auto op = detail::make_op_awaiter(io_uring_prep_cmd_sock, cmd_op, fd, level,
909 optname, optval, optlen);
910 return detail::maybe_flag_fixed_fd(std::move(op), fd);
911}
912#endif
913
914#if !IO_URING_CHECK_VERSION(2, 13) // >= 2.13
918template <FdLike Fd>
919inline auto async_cmd_getsockname(Fd fd, struct sockaddr *sockaddr,
920 socklen_t *sockaddr_len, int peer) {
921 auto op = detail::make_op_awaiter(io_uring_prep_cmd_getsockname, fd,
922 sockaddr, sockaddr_len, peer);
923 return detail::maybe_flag_fixed_fd(std::move(op), fd);
924}
925#endif
926
927#if !IO_URING_CHECK_VERSION(2, 6) // >= 2.6
931inline auto async_waitid(idtype_t idtype, id_t id, siginfo_t *infop,
932 int options, unsigned int flags) {
933 return detail::make_op_awaiter(io_uring_prep_waitid, idtype, id, infop,
934 options, flags);
935}
936#endif
937
938#if !IO_URING_CHECK_VERSION(2, 6) // >= 2.6
942inline auto async_futex_wake(uint32_t *futex, uint64_t val, uint64_t mask,
943 uint32_t futex_flags, unsigned int flags) {
944 return detail::make_op_awaiter(io_uring_prep_futex_wake, futex, val, mask,
945 futex_flags, flags);
946}
947#endif
948
949#if !IO_URING_CHECK_VERSION(2, 6) // >= 2.6
953inline auto async_futex_wait(uint32_t *futex, uint64_t val, uint64_t mask,
954 uint32_t futex_flags, unsigned int flags) {
955 return detail::make_op_awaiter(io_uring_prep_futex_wait, futex, val, mask,
956 futex_flags, flags);
957}
958#endif
959
960#if !IO_URING_CHECK_VERSION(2, 6) // >= 2.6
964inline auto async_futex_waitv(struct futex_waitv *futex, uint32_t nr_futex,
965 unsigned int flags) {
966 return detail::make_op_awaiter(io_uring_prep_futex_waitv, futex, nr_futex,
967 flags);
968}
969#endif
970
971#if !IO_URING_CHECK_VERSION(2, 6) // >= 2.6
975inline auto async_fixed_fd_install(int fixed_fd, unsigned int flags) {
976 return detail::make_op_awaiter(io_uring_prep_fixed_fd_install, fixed_fd,
977 flags);
978}
979#endif
980
981#if !IO_URING_CHECK_VERSION(2, 6) // >= 2.6
985template <FdLike Fd> inline auto async_ftruncate(Fd fd, loff_t len) {
986 auto op = detail::make_op_awaiter(io_uring_prep_ftruncate, fd, len);
987 return detail::maybe_flag_fixed_fd(std::move(op), fd);
988}
989#endif
990
991#if !IO_URING_CHECK_VERSION(2, 8) // >= 2.8
995template <FdLike Fd>
996inline auto async_cmd_discard(Fd fd, uint64_t offset, uint64_t nbytes) {
997 auto op =
998 detail::make_op_awaiter(io_uring_prep_cmd_discard, fd, offset, nbytes);
999 return detail::maybe_flag_fixed_fd(std::move(op), fd);
1000}
1001#endif
1002
1003#if !IO_URING_CHECK_VERSION(2, 7) // >= 2.7
1007template <FdLike Fd>
1008inline auto async_bind(Fd fd, struct sockaddr *addr, socklen_t addrlen) {
1009 auto op = detail::make_op_awaiter(io_uring_prep_bind, fd, addr, addrlen);
1010 return detail::maybe_flag_fixed_fd(std::move(op), fd);
1011}
1012#endif
1013
1014#if !IO_URING_CHECK_VERSION(2, 7) // >= 2.7
1018template <FdLike Fd> inline auto async_listen(Fd fd, int backlog) {
1019 auto op = detail::make_op_awaiter(io_uring_prep_listen, fd, backlog);
1020 return detail::maybe_flag_fixed_fd(std::move(op), fd);
1021}
1022#endif
1023
1027inline auto async_epoll_ctl(int epfd, int fd, int op, struct epoll_event *ev) {
1028 return detail::make_op_awaiter(io_uring_prep_epoll_ctl, epfd, fd, op, ev);
1029}
1030
1031#if !IO_URING_CHECK_VERSION(2, 10) // >= 2.10
1035inline auto async_epoll_wait(int fd, struct epoll_event *events, int maxevents,
1036 unsigned flags) {
1037 return detail::make_op_awaiter(io_uring_prep_epoll_wait, fd, events,
1038 maxevents, flags);
1039}
1040#endif
1041
1042#if !IO_URING_CHECK_VERSION(2, 12) // >= 2.12
1046inline auto async_pipe(int *fds, int pipe_flags) {
1047 return detail::make_op_awaiter(io_uring_prep_pipe, fds, pipe_flags);
1048}
1049#endif
1050
1051#if !IO_URING_CHECK_VERSION(2, 12) // >= 2.12
1055inline auto async_pipe_direct(int *fds, int pipe_flags,
1056 unsigned int file_index) {
1057 return detail::make_op_awaiter(io_uring_prep_pipe_direct, fds, pipe_flags,
1058 file_index);
1059}
1060#endif
1061
1062} // namespace condy
Helper functions for composing asynchronous operations.
A CQE handler that returns the selected buffers based on the result of the CQE.
Buffer pool for zero-copy receive buffers.
Definition zcrx.hpp:67
Definitions of asynchronous operations.
Helper functions for asynchronous operations.
The main namespace for the Condy library.
Definition condy.hpp:37
auto async_read_multishot(Fd fd, Buffer &buf, __u64 offset, MultiShotFunc &&func)
See io_uring_prep_read_multishot.
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_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_fixed_fd_install(int fixed_fd, unsigned int flags)
See io_uring_prep_fixed_fd_install.
auto build_op_awaiter(PrepFunc &&func, Args &&...handler_args)
Build a single-shot operation awaiter with custom CQE handler.
auto async_socket_direct(int domain, int type, int protocol, unsigned file_index, unsigned int flags)
See io_uring_prep_socket_direct.
auto async_madvise64(void *addr, off_t length, int advice)
See io_uring_prep_madvise64.
auto async_fsync(Fd fd, unsigned fsync_flags)
See io_uring_prep_fsync.
auto async_cmd_getsockname(Fd fd, struct sockaddr *sockaddr, socklen_t *sockaddr_len, int peer)
See io_uring_prep_cmd_getsockname.
auto async_ftruncate(Fd fd, loff_t len)
See io_uring_prep_ftruncate.
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 build_multishot_op_awaiter(PrepFunc &&func, MultiShotFunc &&multishot_func, Args &&...handler_args)
Build a multi-shot operation awaiter with custom CQE handler.
auto async_nop128()
See io_uring_prep_nop128.
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_cmd_discard(Fd fd, uint64_t offset, uint64_t nbytes)
See io_uring_prep_cmd_discard.
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_futex_wake(uint32_t *futex, uint64_t val, uint64_t mask, uint32_t futex_flags, unsigned int flags)
See io_uring_prep_futex_wake.
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_epoll_wait(int fd, struct epoll_event *events, int maxevents, unsigned flags)
See io_uring_prep_epoll_wait.
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_fadvise64(Fd fd, __u64 offset, off_t len, int advice)
See io_uring_prep_fadvise64.
auto async_bind(Fd fd, struct sockaddr *addr, socklen_t addrlen)
See io_uring_prep_bind.
auto async_connect(Fd fd, const struct sockaddr *addr, socklen_t addrlen)
See io_uring_prep_connect.
auto async_waitid(idtype_t idtype, id_t id, siginfo_t *infop, int options, unsigned int flags)
See io_uring_prep_waitid.
auto async_files_update(int *fds, unsigned nr_fds, int offset)
See io_uring_prep_files_update.
auto async_cmd_sock(int cmd_op, Fd fd, int level, int optname, void *optval, int optlen)
See io_uring_prep_cmd_sock.
auto async_read(Fd fd, const Buffer &buf, __u64 offset)
See io_uring_prep_read.
auto async_tee(Fd1 fd_in, Fd2 fd_out, unsigned int nbytes, unsigned int splice_flags)
See io_uring_prep_tee.
auto async_write(Fd fd, const Buffer &buf, __u64 offset)
See io_uring_prep_write.
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_futex_wait(uint32_t *futex, uint64_t val, uint64_t mask, uint32_t futex_flags, unsigned int flags)
See io_uring_prep_futex_wait.
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_pipe_direct(int *fds, int pipe_flags, unsigned int file_index)
See io_uring_prep_pipe_direct.
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_cmd128(int cmd_op, Fd fd, CmdFunc &&cmd_func)
See io_uring_prep_uring_cmd128.
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_listen(Fd fd, int backlog)
See io_uring_prep_listen.
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 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_timeout_multishot(struct __kernel_timespec *ts, unsigned count, unsigned flags, MultiShotFunc &&func)
See io_uring_prep_timeout.
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)
See io_uring_prep_uring_cmd.
auto async_pipe(int *fds, int pipe_flags)
See io_uring_prep_pipe.
auto async_futex_waitv(struct futex_waitv *futex, uint32_t nr_futex, unsigned int flags)
See io_uring_prep_futex_waitv.
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.
auto async_uring_cmd_multishot(int cmd_op, Fd fd, CmdFunc &&cmd_func, MultiShotFunc &&func)
See io_uring_prep_uring_cmd.