Skip to content

Commit b29ec77

Browse files
authored
chore: use afit and rpitit (#217)
1 parent d5bf594 commit b29ec77

32 files changed

+707
-1237
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ A thread-per-core Rust runtime with io_uring/epoll/kqueue.
1919
[zh-readme-url]: README-zh.md
2020

2121
## Design Goal
22-
Monoio is a pure io_uring/epoll/kqueue Rust async runtime. Part of the design has been borrowed from Tokio and Tokio-uring. However, unlike Tokio-uring, Monoio does not run on top of another runtime, rendering it more efficient.
22+
Monoio is a pure io_uring/epoll/kqueue Rust async runtime. Part of the design has been borrowed from Tokio and Tokio-uring. However, unlike Tokio-uring, Monoio does not run on top of another runtime, rendering it more efficient.
2323

2424
Moreover, Monoio is designed with a thread-per-core model in mind. Users do not need to worry about tasks being `Send` or `Sync`, as thread local storage can be used safely. In other words, the data does not escape the thread on await points, unlike on work-stealing runtimes such as Tokio. This is because for some use cases, specifically those targeted by this runtime, it is not necessary to make task schedulable between threads. For example, if we were to write a load balancer like NGINX, we would write it in a thread-per-core way. The thread local data does not need to be shared between threads, so the `Sync` and `Send` do not need to be implemented in the first place.
2525

docs/en/io-cancel.md

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
---
22
title: Cancel IO
33
date: 2023-02-27 15:09:00
4+
updated: 2023-11-06 16:49:00
45
author: ihciah
56
---
67

@@ -14,28 +15,17 @@ Taking reads as an example, the following code defines a cancelable asynchronous
1415
```rust
1516
/// CancelableAsyncReadRent: async read with an ownership of a buffer and ability to cancel io.
1617
pub trait CancelableAsyncReadRent: AsyncReadRent {
17-
/// The future of read Result<size, buffer>
18-
type CancelableReadFuture<'a, T>: Future<Output = BufResult<usize, T>>
19-
where
20-
Self: 'a,
21-
T: IoBufMut + 'a;
22-
/// The future of readv Result<size, buffer>
23-
type CancelableReadvFuture<'a, T>: Future<Output = BufResult<usize, T>>
24-
where
25-
Self: 'a,
26-
T: IoVecBufMut + 'a;
27-
2818
fn cancelable_read<T: IoBufMut>(
2919
&mut self,
3020
buf: T,
3121
c: CancelHandle,
32-
) -> Self::CancelableReadFuture<'_, T>;
22+
) -> impl Future<Output = BufResult<usize, T>>;
3323

3424
fn cancelable_readv<T: IoVecBufMut>(
3525
&mut self,
3626
buf: T,
3727
c: CancelHandle,
38-
) -> Self::CancelableReadvFuture<'_, T>;
28+
) -> impl Future<Output = BufResult<usize, T>>;
3929
}
4030
```
4131

docs/en/why-GAT.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
---
22
title: Why GAT
33
date: 2021-11-24 20:00:00
4+
updated: 2023-11-06 16:49:00
45
author: ihciah
56
---
67

@@ -39,3 +40,17 @@ trait AsyncReadRent {
3940
```
4041

4142
The only problem here is, if you use GAT style, you should always use it. Providing `poll` style based on GAT is not easy. As an example, `monoio-compat` implement tokio `AsyncRead` and `AsyncWrite` based on GAT style future with some unsafe hack(and also with a `Box` cost).
43+
44+
## async_fn_in_trait
45+
`async_fn_in_trait` and `return_position_impl_trait_in_trait` is stable now in rust and can be used to replace GAT usage here(related [issue](https://github.com/rust-lang/rust/issues/91611)).
46+
47+
Now we can define and impl async trait easier:
48+
```rust
49+
trait AsyncReadRent {
50+
fn read<T: IoBufMut>(&mut self, buf: T) -> impl Future<Output = BufResult<usize, T>>;
51+
}
52+
53+
impl AsyncReadRent for Demo {
54+
async fn read<T: IoBufMut>(&mut self, buf: T) -> BufResult<usize, T> { ... }
55+
}
56+
```

docs/zh/io-cancel.md

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
---
22
title: 取消 IO
33
date: 2023-02-27 15:09:00
4+
updated: 2023-11-06 16:49:00
45
author: ihciah
56
---
67

@@ -14,28 +15,17 @@ author: ihciah
1415
```rust
1516
/// CancelableAsyncReadRent: async read with a ownership of a buffer and ability to cancel io.
1617
pub trait CancelableAsyncReadRent: AsyncReadRent {
17-
/// The future of read Result<size, buffer>
18-
type CancelableReadFuture<'a, T>: Future<Output = BufResult<usize, T>>
19-
where
20-
Self: 'a,
21-
T: IoBufMut + 'a;
22-
/// The future of readv Result<size, buffer>
23-
type CancelableReadvFuture<'a, T>: Future<Output = BufResult<usize, T>>
24-
where
25-
Self: 'a,
26-
T: IoVecBufMut + 'a;
27-
2818
fn cancelable_read<T: IoBufMut>(
2919
&mut self,
3020
buf: T,
3121
c: CancelHandle,
32-
) -> Self::CancelableReadFuture<'_, T>;
22+
) -> impl Future<Output = BufResult<usize, T>>;
3323

3424
fn cancelable_readv<T: IoVecBufMut>(
3525
&mut self,
3626
buf: T,
3727
c: CancelHandle,
38-
) -> Self::CancelableReadvFuture<'_, T>;
28+
) -> impl Future<Output = BufResult<usize, T>>;
3929
}
4030
```
4131

docs/zh/why-GAT.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
---
22
title: 为什么使用 GAT
33
date: 2021-11-24 20:00:00
4+
updated: 2023-11-06 16:49:00
45
author: ihciah
56
---
67

@@ -42,3 +43,17 @@ trait AsyncReadRent {
4243
```
4344

4445
这是银弹吗?不是。唯一的问题在于,如果使用了 GAT 这一套模式,就要总是使用它。如果你在 `poll` 形式和 GAT 形式之间反复横跳,那你会十分痛苦。基于 `poll` 形式接口自行维护状态,确实可以实现 Future(最简单的实现如 `poll_fn`);但反过来就很难受了:你很难存储一个带生命周期的 Future。虽然使用一些 unsafe 的 hack 可以做(也有 cost)这件事,但是仍旧,限制很多且并不推荐这么做。`monoio-compat` 基于 GAT 的 future 实现了 Tokio 的 `AsyncRead``AsyncWrite`,如果你非要试一试,可以参考它。
46+
47+
## async_fn_in_trait
48+
Rust 已经稳定了 `async_fn_in_trait`,结合 `return_position_impl_trait_in_trait` 可以替代这里的 GAT(相关 [issue](https://github.com/rust-lang/rust/issues/91611))。
49+
50+
现在我们可以更简单地定义并实现 trait:
51+
```rust
52+
trait AsyncReadRent {
53+
fn read<T: IoBufMut>(&mut self, buf: T) -> impl Future<Output = BufResult<usize, T>>;
54+
}
55+
56+
impl AsyncReadRent for Demo {
57+
async fn read<T: IoBufMut>(&mut self, buf: T) -> BufResult<usize, T> { ... }
58+
}
59+
```

monoio-compat/Cargo.toml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,12 @@ license = "MIT/Apache-2.0"
88
name = "monoio-compat"
99
readme = "README.md"
1010
repository = "https://github.com/bytedance/monoio"
11-
version = "0.1.2"
11+
version = "0.2.0"
1212

1313
[dependencies]
14-
monoio = {version = "0.1.0", path = "../monoio", default-features = false}
14+
monoio = {version = "0.2.0", path = "../monoio", default-features = false}
1515
reusable-box-future = "0.2"
1616
tokio = {version = "1", default-features = false, features = ["io-util"]}
1717

1818
[dev-dependencies]
19-
monoio = {version = "0.1.0", path = "../monoio", features = ["async-cancel", "macros"]}
19+
monoio = {version = "0.2.0", path = "../monoio", features = ["async-cancel", "macros"]}

monoio/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ license = "MIT/Apache-2.0"
88
name = "monoio"
99
readme = "../README.md"
1010
repository = "https://github.com/bytedance/monoio"
11-
version = "0.1.9"
11+
version = "0.2.0"
1212

1313
# common dependencies
1414
[dependencies]

monoio/src/io/async_buf_read.rs

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,8 @@ use crate::io::AsyncReadRent;
44

55
/// AsyncBufRead: async read with buffered content
66
pub trait AsyncBufRead: AsyncReadRent {
7-
/// The returned future of fill_buf
8-
type FillBufFuture<'a>: Future<Output = std::io::Result<&'a [u8]>>
9-
where
10-
Self: 'a;
11-
127
/// Try read data and get a reference to the internal buffer
13-
fn fill_buf(&mut self) -> Self::FillBufFuture<'_>;
8+
fn fill_buf(&mut self) -> impl Future<Output = std::io::Result<&[u8]>>;
149
/// Mark how much data is read
1510
fn consume(&mut self, amt: usize);
1611
}

monoio/src/io/async_buf_read_ext.rs

Lines changed: 28 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -55,11 +55,6 @@ where
5555

5656
/// AsyncBufReadExt
5757
pub trait AsyncBufReadExt {
58-
/// The future of read until Result<usize>
59-
type ReadUntilFuture<'a>: Future<Output = Result<usize>>
60-
where
61-
Self: 'a;
62-
6358
/// This function will read bytes from the underlying stream until the delimiter or EOF is
6459
/// found. Once found, all bytes up to, and including, the delimiter (if found) will be appended
6560
/// to buf.
@@ -69,12 +64,11 @@ pub trait AsyncBufReadExt {
6964
/// # Errors
7065
/// This function will ignore all instances of ErrorKind::Interrupted and will otherwise return
7166
/// any errors returned by fill_buf.
72-
fn read_until<'a>(&'a mut self, byte: u8, buf: &'a mut Vec<u8>) -> Self::ReadUntilFuture<'a>;
73-
74-
/// The future of read line Result<usize>
75-
type ReadLineFuture<'a>: Future<Output = Result<usize>>
76-
where
77-
Self: 'a;
67+
fn read_until<'a>(
68+
&'a mut self,
69+
byte: u8,
70+
buf: &'a mut Vec<u8>,
71+
) -> impl Future<Output = Result<usize>>;
7872

7973
/// This function will read bytes from the underlying stream until the newline delimiter (the
8074
/// 0xA byte) or EOF is found. Once found, all bytes up to, and including, the delimiter (if
@@ -88,41 +82,39 @@ pub trait AsyncBufReadExt {
8882
/// This function has the same error semantics as read_until and will also return an error if
8983
/// the read bytes are not valid UTF-8. If an I/O error is encountered then buf may contain some
9084
/// bytes already read in the event that all data read so far was valid UTF-8.
91-
fn read_line<'a>(&'a mut self, buf: &'a mut String) -> Self::ReadLineFuture<'a>;
85+
fn read_line<'a>(&'a mut self, buf: &'a mut String) -> impl Future<Output = Result<usize>>;
9286
}
9387

9488
impl<A> AsyncBufReadExt for A
9589
where
9690
A: AsyncBufRead + ?Sized,
9791
{
98-
type ReadUntilFuture<'a> = impl Future<Output = Result<usize>> + 'a where Self: 'a;
99-
100-
fn read_until<'a>(&'a mut self, byte: u8, buf: &'a mut Vec<u8>) -> Self::ReadUntilFuture<'a> {
92+
fn read_until<'a>(
93+
&'a mut self,
94+
byte: u8,
95+
buf: &'a mut Vec<u8>,
96+
) -> impl Future<Output = Result<usize>> {
10197
read_until(self, byte, buf)
10298
}
10399

104-
type ReadLineFuture<'a> = impl Future<Output = Result<usize>> + 'a where Self: 'a;
105-
106-
fn read_line<'a>(&'a mut self, buf: &'a mut String) -> Self::ReadLineFuture<'a> {
107-
async {
108-
unsafe {
109-
let mut g = Guard {
110-
len: buf.len(),
111-
buf: buf.as_mut_vec(),
112-
};
100+
async fn read_line<'a>(&'a mut self, buf: &'a mut String) -> Result<usize> {
101+
unsafe {
102+
let mut g = Guard {
103+
len: buf.len(),
104+
buf: buf.as_mut_vec(),
105+
};
113106

114-
let ret = read_until(self, b'\n', g.buf).await;
115-
if from_utf8(&g.buf[g.len..]).is_err() {
116-
ret.and_then(|_| {
117-
Err(Error::new(
118-
ErrorKind::InvalidData,
119-
"stream did not contain valid UTF-8",
120-
))
121-
})
122-
} else {
123-
g.len = g.buf.len();
124-
ret
125-
}
107+
let ret = read_until(self, b'\n', g.buf).await;
108+
if from_utf8(&g.buf[g.len..]).is_err() {
109+
ret.and_then(|_| {
110+
Err(Error::new(
111+
ErrorKind::InvalidData,
112+
"stream did not contain valid UTF-8",
113+
))
114+
})
115+
} else {
116+
g.len = g.buf.len();
117+
ret
126118
}
127119
}
128120
}

monoio/src/io/async_read_rent.rs

Lines changed: 12 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -7,64 +7,36 @@ use crate::{
77

88
/// AsyncReadRent: async read with a ownership of a buffer
99
pub trait AsyncReadRent {
10-
/// The future of read Result<size, buffer>
11-
type ReadFuture<'a, T>: Future<Output = BufResult<usize, T>>
12-
where
13-
Self: 'a,
14-
T: IoBufMut + 'a;
15-
/// The future of readv Result<size, buffer>
16-
type ReadvFuture<'a, T>: Future<Output = BufResult<usize, T>>
17-
where
18-
Self: 'a,
19-
T: IoVecBufMut + 'a;
20-
2110
/// Same as read(2)
22-
fn read<T: IoBufMut>(&mut self, buf: T) -> Self::ReadFuture<'_, T>;
11+
fn read<T: IoBufMut>(&mut self, buf: T) -> impl Future<Output = BufResult<usize, T>>;
2312
/// Same as readv(2)
24-
fn readv<T: IoVecBufMut>(&mut self, buf: T) -> Self::ReadvFuture<'_, T>;
13+
fn readv<T: IoVecBufMut>(&mut self, buf: T) -> impl Future<Output = BufResult<usize, T>>;
2514
}
2615

2716
/// AsyncReadRentAt: async read with a ownership of a buffer and a position
2817
pub trait AsyncReadRentAt {
29-
/// The future of Result<size, buffer>
30-
type Future<'a, T>: Future<Output = BufResult<usize, T>>
31-
where
32-
Self: 'a,
33-
T: 'a;
34-
35-
/// Same as Read(2)
36-
fn read_at<T: IoBufMut>(&mut self, buf: T, pos: usize) -> Self::Future<'_, T>;
18+
/// Same as pread(2)
19+
fn read_at<T: IoBufMut>(
20+
&mut self,
21+
buf: T,
22+
pos: usize,
23+
) -> impl Future<Output = BufResult<usize, T>>;
3724
}
3825

3926
impl<A: ?Sized + AsyncReadRent> AsyncReadRent for &mut A {
40-
type ReadFuture<'a, T> = A::ReadFuture<'a, T>
41-
where
42-
Self: 'a,
43-
T: IoBufMut + 'a;
44-
45-
type ReadvFuture<'a, T> = A::ReadvFuture<'a, T>
46-
where
47-
Self: 'a,
48-
T: IoVecBufMut + 'a;
49-
5027
#[inline]
51-
fn read<T: IoBufMut>(&mut self, buf: T) -> Self::ReadFuture<'_, T> {
28+
fn read<T: IoBufMut>(&mut self, buf: T) -> impl Future<Output = BufResult<usize, T>> {
5229
(**self).read(buf)
5330
}
5431

5532
#[inline]
56-
fn readv<T: IoVecBufMut>(&mut self, buf: T) -> Self::ReadvFuture<'_, T> {
33+
fn readv<T: IoVecBufMut>(&mut self, buf: T) -> impl Future<Output = BufResult<usize, T>> {
5734
(**self).readv(buf)
5835
}
5936
}
6037

6138
impl AsyncReadRent for &[u8] {
62-
type ReadFuture<'a, B> = impl std::future::Future<Output = crate::BufResult<usize, B>> where
63-
B: IoBufMut + 'a, Self: 'a;
64-
type ReadvFuture<'a, B> = impl std::future::Future<Output = crate::BufResult<usize, B>> where
65-
B: IoVecBufMut + 'a, Self: 'a;
66-
67-
fn read<T: IoBufMut>(&mut self, mut buf: T) -> Self::ReadFuture<'_, T> {
39+
fn read<T: IoBufMut>(&mut self, mut buf: T) -> impl Future<Output = BufResult<usize, T>> {
6840
let amt = std::cmp::min(self.len(), buf.bytes_total());
6941
let (a, b) = self.split_at(amt);
7042
unsafe {
@@ -75,7 +47,7 @@ impl AsyncReadRent for &[u8] {
7547
async move { (Ok(amt), buf) }
7648
}
7749

78-
fn readv<T: IoVecBufMut>(&mut self, mut buf: T) -> Self::ReadvFuture<'_, T> {
50+
fn readv<T: IoVecBufMut>(&mut self, mut buf: T) -> impl Future<Output = BufResult<usize, T>> {
7951
// # Safety
8052
// We do it in pure sync way.
8153
let n = match unsafe { RawBuf::new_from_iovec_mut(&mut buf) } {

0 commit comments

Comments
 (0)