diff --git a/Cargo.lock b/Cargo.lock
index 68212f05bc9421..ff38a20061b8b8 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1182,6 +1182,7 @@ dependencies = [
"serde",
"socket2",
"tokio",
+ "tokio-uring",
"trust-dns-proto",
"trust-dns-resolver",
]
@@ -1257,6 +1258,7 @@ dependencies = [
"termcolor",
"test_util",
"tokio",
+ "tokio-uring",
"uuid",
"winapi 0.3.9",
"winres",
@@ -2442,6 +2444,16 @@ version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ea37f355c05dde75b84bba2d767906ad522e97cd9e2eef2be7a4ab7fb442c06"
+[[package]]
+name = "io-uring"
+version = "0.5.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6d32c9c053ad47572e11da8bce622ed4c9ae9dedac5b7f678a2e876d1494d4c4"
+dependencies = [
+ "bitflags",
+ "libc",
+]
+
[[package]]
name = "ipconfig"
version = "0.3.0"
@@ -4076,6 +4088,7 @@ dependencies = [
"serde_bytes",
"serde_json",
"smallvec",
+ "tokio-uring",
"v8",
]
@@ -5010,6 +5023,18 @@ dependencies = [
"webpki-roots",
]
+[[package]]
+name = "tokio-uring"
+version = "0.3.0"
+dependencies = [
+ "io-uring",
+ "libc",
+ "scoped-tls",
+ "slab",
+ "socket2",
+ "tokio",
+]
+
[[package]]
name = "tokio-util"
version = "0.7.4"
diff --git a/a.svg b/a.svg
new file mode 100644
index 00000000000000..e5b1104a8a427c
--- /dev/null
+++ b/a.svg
@@ -0,0 +1,415 @@
+
\ No newline at end of file
diff --git a/cli/bench/read_file.js b/cli/bench/read_file.js
new file mode 100644
index 00000000000000..d9cc2209c2c313
--- /dev/null
+++ b/cli/bench/read_file.js
@@ -0,0 +1,21 @@
+// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
+const queueMicrotask = globalThis.queueMicrotask || process.nextTick;
+let [total, count] = typeof Deno !== "undefined"
+ ? Deno.args
+ : [process.argv[2], process.argv[3]];
+
+total = total ? parseInt(total, 0) : 50;
+count = count ? parseInt(count, 10) : 1000;
+
+async function bench(fun) {
+ const start = Date.now();
+ for (let i = 0; i < count; i++) await fun();
+ const elapsed = Date.now() - start;
+ const rate = Math.floor(count / (elapsed / 1000));
+ console.log(`time ${elapsed} ms rate ${rate}`);
+ if (--total) queueMicrotask(() => bench(fun));
+}
+
+const x = new TextEncoder().encode("lol\n".repeat(1024 * 1024));
+await Deno.writeFile("a.txt", x);
+await bench(() => Deno.readFile("a.txt"));
diff --git a/cli/bench/write_file.js b/cli/bench/write_file.js
index 2f09b36451aa7f..7382966c1b0720 100644
--- a/cli/bench/write_file.js
+++ b/cli/bench/write_file.js
@@ -5,7 +5,7 @@ let [total, count] = typeof Deno !== "undefined"
: [process.argv[2], process.argv[3]];
total = total ? parseInt(total, 0) : 50;
-count = count ? parseInt(count, 10) : 10000;
+count = count ? parseInt(count, 10) : 100;
async function bench(fun) {
const start = Date.now();
@@ -16,6 +16,7 @@ async function bench(fun) {
if (--total) queueMicrotask(() => bench(fun));
}
-bench(() => Deno.writeFile("/dev/null", new Uint8Array(10)));
+const x = new TextEncoder().encode("lol\n".repeat(1024 * 1024));
+await bench(() => Deno.writeFile("a.txt", x));
// const fs = require("fs").promises;
-// bench(() => fs.writeFile("/dev/null", new Uint8Array(10)));
+// bench(() => fs.writeFile("/dev/null", x));
diff --git a/core/Cargo.toml b/core/Cargo.toml
index 57dafa0e50cb76..e554e81f0d0abb 100644
--- a/core/Cargo.toml
+++ b/core/Cargo.toml
@@ -15,6 +15,7 @@ path = "lib.rs"
[features]
default = ["v8_use_custom_libcxx"]
v8_use_custom_libcxx = ["v8/use_custom_libcxx"]
+enable_iouring = ["serde_v8/enable_iouring"]
[dependencies]
anyhow = "1.0.57"
diff --git a/dump.md b/dump.md
new file mode 100644
index 00000000000000..15afaf1d509df3
--- /dev/null
+++ b/dump.md
@@ -0,0 +1,15 @@
+```
+divy@divy:~/deno$ target/release/deno run -A --unstable cli/bench/write_file.js
+time 433 ms rate 230
+time 548 ms rate 182
+time 540 ms rate 185
+time 565 ms rate 176
+^C
+
+divy@divy:~/deno$ ~/.deno/bin/deno run -A --unstable cli/bench/write_file.js
+time 2696 ms rate 37
+time 2857 ms rate 35
+time 2859 ms rate 34
+time 2861 ms rate 34
+^C
+```
diff --git a/ext/net/Cargo.toml b/ext/net/Cargo.toml
index f278f69c1950af..1552e93eb3351e 100644
--- a/ext/net/Cargo.toml
+++ b/ext/net/Cargo.toml
@@ -20,5 +20,6 @@ log = "0.4.16"
serde = { version = "1.0.136", features = ["derive"] }
socket2 = "0.4.4"
tokio = { version = "1.21", features = ["full"] }
+tokio-uring = { version = "0.3.0", path = "../../../tokio-uring" }
trust-dns-proto = "0.22"
trust-dns-resolver = { version = "0.22", features = ["tokio-runtime", "serde-config"] }
diff --git a/ext/net/ops.rs b/ext/net/ops.rs
index 41d04467eaeced..18174289832bf3 100644
--- a/ext/net/ops.rs
+++ b/ext/net/ops.rs
@@ -31,8 +31,9 @@ use std::borrow::Cow;
use std::cell::RefCell;
use std::net::SocketAddr;
use std::rc::Rc;
-use tokio::net::TcpListener;
-use tokio::net::TcpStream;
+// use tokio::net::TcpListener;
+use tokio_uring::net::TcpStream;
+// use tokio::net::TcpStream;
use tokio::net::UdpSocket;
use trust_dns_proto::rr::rdata::caa::Value;
use trust_dns_proto::rr::record_data::RData;
@@ -109,6 +110,58 @@ pub(crate) struct AcceptArgs {
pub transport: String,
}
+pub struct IoUringTcpStreamResource {
+ stream: tokio_uring::net::TcpStream,
+}
+
+impl Resource for IoUringTcpStreamResource {
+ deno_core::impl_readable_byob!();
+ deno_core::impl_writable!();
+ fn name(&self) -> Cow {
+ "ioUringTcpStream".into()
+ }
+
+ fn shutdown(self: Rc) -> AsyncResult<()> {
+ todo!();
+ // Box::pin(Ok(()))
+ }
+
+ fn close(self: Rc) {
+ // ...
+ }
+}
+
+impl IoUringTcpStreamResource {
+ pub fn new(stream: tokio_uring::net::TcpStream) -> Self {
+ Self { stream }
+ }
+
+ pub async fn read(
+ self: Rc,
+ data: &mut [u8],
+ ) -> Result {
+ let (nread, _) = self.stream.read(data.to_vec()).await;
+ Ok(nread?)
+ }
+
+ pub async fn write(self: Rc, data: &[u8]) -> Result {
+ // LMAO divy wtf...
+ let data: &'static [u8] = unsafe { std::mem::transmute(data) };
+ let (nwritten, _) = self.stream.write(data).await;
+ Ok(nwritten?)
+ }
+}
+
+use deno_core::AsyncResult;
+use std::ops::Deref;
+
+impl Deref for IoUringTcpStreamResource {
+ type Target = tokio_uring::net::TcpStream;
+ fn deref(&self) -> &Self::Target {
+ &self.stream
+ }
+}
+
pub(crate) fn accept_err(e: std::io::Error) -> AnyError {
// FIXME(bartlomieju): compatibility with current JS implementation
if let std::io::ErrorKind::Interrupted = e.kind() {
@@ -139,23 +192,18 @@ async fn accept_tcp(
.try_or_cancel(cancel)
.await
.map_err(accept_err)?;
- let local_addr = tcp_stream.local_addr()?;
- let remote_addr = tcp_stream.peer_addr()?;
+ // let local_addr = tcp_stream.local_addr()?;
+ // let remote_addr = tcp_stream.peer_addr()?;
+ let tcp_stream = TcpStream::from_std(tcp_stream.into_std()?);
let mut state = state.borrow_mut();
let rid = state
.resource_table
- .add(TcpStreamResource::new(tcp_stream.into_split()));
+ .add(IoUringTcpStreamResource::new(tcp_stream));
Ok(OpConn {
rid,
- local_addr: Some(OpAddr::Tcp(IpAddr {
- hostname: local_addr.ip().to_string(),
- port: local_addr.port(),
- })),
- remote_addr: Some(OpAddr::Tcp(IpAddr {
- hostname: remote_addr.ip().to_string(),
- port: remote_addr.port(),
- })),
+ local_addr: None,
+ remote_addr: None,
})
}
@@ -328,24 +376,18 @@ where
.await?
.next()
.ok_or_else(|| generic_error("No resolved address found"))?;
- let tcp_stream = TcpStream::connect(&addr).await?;
- let local_addr = tcp_stream.local_addr()?;
- let remote_addr = tcp_stream.peer_addr()?;
+ let tcp_stream = TcpStream::connect(addr).await?;
+ // let local_addr = tcp_stream.local_addr()?;
+ // let remote_addr = tcp_stream.peer_addr()?;
let mut state_ = state.borrow_mut();
let rid = state_
.resource_table
- .add(TcpStreamResource::new(tcp_stream.into_split()));
+ .add(IoUringTcpStreamResource::new(tcp_stream));
Ok(OpConn {
rid,
- local_addr: Some(OpAddr::Tcp(IpAddr {
- hostname: local_addr.ip().to_string(),
- port: local_addr.port(),
- })),
- remote_addr: Some(OpAddr::Tcp(IpAddr {
- hostname: remote_addr.ip().to_string(),
- port: remote_addr.port(),
- })),
+ local_addr: None,
+ remote_addr: None,
})
}
#[cfg(unix)]
@@ -387,7 +429,7 @@ where
}
pub struct TcpListenerResource {
- pub listener: AsyncRefCell,
+ pub listener: AsyncRefCell,
pub cancel: CancelHandle,
}
@@ -454,7 +496,7 @@ fn listen_tcp(
socket.listen(128)?;
socket.set_nonblocking(true)?;
let std_listener: std::net::TcpListener = socket.into();
- let listener = TcpListener::from_std(std_listener)?;
+ let listener = tokio::net::TcpListener::from_std(std_listener)?;
let local_addr = listener.local_addr()?;
let listener_resource = TcpListenerResource {
listener: AsyncRefCell::new(listener),
@@ -727,9 +769,10 @@ pub fn op_set_nodelay(
nodelay: bool,
) -> Result<(), AnyError> {
super::check_unstable(state, "Deno.Conn#setNoDelay");
- let resource: Rc =
- state.resource_table.get::(rid)?;
- resource.set_nodelay(nodelay)
+ // let resource: Rc =
+ // state.resource_table.get::(rid)?;
+ // resource.set_nodelay(nodelay)
+ Ok(())
}
#[op]
@@ -739,9 +782,10 @@ pub fn op_set_keepalive(
keepalive: bool,
) -> Result<(), AnyError> {
super::check_unstable(state, "Deno.Conn#setKeepAlive");
- let resource: Rc =
- state.resource_table.get::(rid)?;
- resource.set_keepalive(keepalive)
+ // let resource: Rc =
+ // state.resource_table.get::(rid)?;
+ // resource.set_keepalive(keepalive)
+ Ok(())
}
fn rdata_to_return_record(
diff --git a/runtime/Cargo.toml b/runtime/Cargo.toml
index 1d4fbe5c9a631c..6de9fc296a0782 100644
--- a/runtime/Cargo.toml
+++ b/runtime/Cargo.toml
@@ -12,6 +12,7 @@ description = "Provides the deno runtime library"
[features]
# "fake" feature that allows to generate docs on docs.rs
docsrs = []
+enable_iouring = ["deno_core/enable_iouring", "tokio-uring"]
[lib]
name = "deno_runtime"
@@ -97,6 +98,7 @@ winapi = { version = "0.3.9", features = ["commapi", "knownfolders", "mswsock",
[target.'cfg(unix)'.dependencies]
nix = "=0.24.2"
+tokio-uring = { version = "0.3.0", path = "../../tokio-uring", optional = true }
[dev-dependencies]
# Used in benchmark
diff --git a/runtime/ops/asyncfs/iouring/mod.rs b/runtime/ops/asyncfs/iouring/mod.rs
new file mode 100644
index 00000000000000..0bf50afad626fe
--- /dev/null
+++ b/runtime/ops/asyncfs/iouring/mod.rs
@@ -0,0 +1,159 @@
+use crate::ops::fs::write_open_options;
+
+use crate::ops::fs::OpenOptions;
+use crate::permissions::Permissions;
+use deno_core::error::AnyError;
+use deno_core::op;
+use deno_core::CancelFuture;
+use deno_core::CancelHandle;
+use deno_core::OpState;
+use deno_core::ResourceId;
+use deno_core::ZeroCopyBuf;
+use std::cell::RefCell;
+use std::path::Path;
+use std::path::PathBuf;
+use std::rc::Rc;
+use tokio_uring::fs::File;
+
+#[inline]
+pub(crate) fn open_helper_async(
+ state: &mut OpState,
+ path: &str,
+ mode: Option,
+ options: Option<&OpenOptions>,
+ api_name: &str,
+) -> Result<(PathBuf, tokio_uring::fs::OpenOptions), AnyError> {
+ let path = Path::new(path).to_path_buf();
+
+ let mut open_options = tokio_uring::fs::OpenOptions::new();
+
+ if let Some(mode) = mode {
+ // mode only used if creating the file on Unix
+ // if not specified, defaults to 0o666
+ #[cfg(unix)]
+ {
+ use std::os::unix::fs::OpenOptionsExt;
+ open_options.mode(mode & 0o777);
+ }
+ #[cfg(not(unix))]
+ let _ = mode; // avoid unused warning
+ }
+
+ let permissions = state.borrow_mut::();
+
+ match options {
+ None => {
+ permissions.read.check(&path, Some(api_name))?;
+ open_options
+ .read(true)
+ .create(false)
+ .write(false)
+ .truncate(false)
+ .append(false)
+ .create_new(false);
+ }
+ Some(options) => {
+ if options.read {
+ permissions.read.check(&path, Some(api_name))?;
+ }
+
+ if options.write || options.append {
+ permissions.write.check(&path, Some(api_name))?;
+ }
+
+ open_options
+ .read(options.read)
+ .create(options.create)
+ .write(options.write)
+ .truncate(options.truncate)
+ .append(options.append)
+ .create_new(options.create_new);
+ }
+ }
+
+ Ok((path, open_options))
+}
+
+#[op]
+pub async fn op_write_file_async(
+ state: Rc>,
+ path: String,
+ mode: Option,
+ append: bool,
+ create: bool,
+ data: ZeroCopyBuf,
+ cancel_rid: Option,
+) -> Result<(), AnyError> {
+ let cancel_handle = match cancel_rid {
+ Some(cancel_rid) => state
+ .borrow_mut()
+ .resource_table
+ .get::(cancel_rid)
+ .ok(),
+ None => None,
+ };
+ let (path, open_options) = open_helper_async(
+ &mut *state.borrow_mut(),
+ &path,
+ mode,
+ Some(&write_open_options(create, append)),
+ "Deno.writeFile()",
+ )?;
+ let write_future = async move {
+ let file = open_options.open(&path).await?;
+ let (res, _) = file.write_all_at(data, 0).await;
+ res?;
+ Ok::<(), AnyError>(())
+ };
+ if let Some(cancel_handle) = cancel_handle {
+ write_future.or_cancel(cancel_handle).await??;
+ } else {
+ write_future.await?;
+ }
+ Ok(())
+}
+
+#[op]
+async fn op_readfile_async(
+ state: Rc>,
+ path: String,
+ cancel_rid: Option,
+) -> Result {
+ {
+ let path = Path::new(&path);
+ let mut state = state.borrow_mut();
+ state
+ .borrow_mut::()
+ .read
+ .check(path, Some("Deno.readFile()"))?;
+ }
+
+ // TODO(@littledivy): Stat file to get the size.
+ let fut = async move {
+ let path = Path::new(&path);
+ let file = File::open(&path).await?;
+ let mut buf = vec![0; 1024 * 16];
+ let mut offset: u64 = 0;
+ loop {
+ let (res, mut ret) =
+ file.read_at(buf.split_off(offset as usize), offset).await;
+ let nread = res? as u64;
+ offset = offset + nread;
+ if nread == 0 {
+ break Ok::(ret.into());
+ }
+ ret.resize(offset as usize * 2, 0);
+ buf = ret;
+ }
+ };
+ if let Some(cancel_rid) = cancel_rid {
+ let cancel_handle = state
+ .borrow_mut()
+ .resource_table
+ .get::(cancel_rid);
+ if let Ok(cancel_handle) = cancel_handle {
+ return fut.or_cancel(cancel_handle).await?;
+ }
+ }
+ fut.await
+}
diff --git a/runtime/ops/asyncfs/mod.rs b/runtime/ops/asyncfs/mod.rs
new file mode 100644
index 00000000000000..d41701d0873328
--- /dev/null
+++ b/runtime/ops/asyncfs/mod.rs
@@ -0,0 +1,10 @@
+#[cfg(feature = "enable_iouring")]
+pub mod iouring;
+#[cfg(not(feature = "enable_iouring"))]
+pub mod spawn_blocking;
+
+#[cfg(feature = "enable_iouring")]
+pub use iouring::*;
+
+#[cfg(not(feature = "enable_iouring"))]
+pub use spawn_blocking::*;
diff --git a/runtime/ops/asyncfs/spawn_blocking/mod.rs b/runtime/ops/asyncfs/spawn_blocking/mod.rs
new file mode 100644
index 00000000000000..c9364be4f2d585
--- /dev/null
+++ b/runtime/ops/asyncfs/spawn_blocking/mod.rs
@@ -0,0 +1,81 @@
+use crate::ops::fs::open_helper;
+use crate::ops::fs::write_file;
+use crate::ops::fs::write_open_options;
+
+use crate::permissions::Permissions;
+use deno_core::error::AnyError;
+use deno_core::op;
+use deno_core::CancelFuture;
+use deno_core::CancelHandle;
+use deno_core::OpState;
+use deno_core::ResourceId;
+use deno_core::ZeroCopyBuf;
+use std::cell::RefCell;
+use std::path::Path;
+use std::rc::Rc;
+
+#[op]
+pub async fn op_write_file_async(
+ state: Rc>,
+ path: String,
+ mode: Option,
+ append: bool,
+ create: bool,
+ data: ZeroCopyBuf,
+ cancel_rid: Option,
+) -> Result<(), AnyError> {
+ let cancel_handle = match cancel_rid {
+ Some(cancel_rid) => state
+ .borrow_mut()
+ .resource_table
+ .get::(cancel_rid)
+ .ok(),
+ None => None,
+ };
+ let (path, open_options) = open_helper(
+ &mut *state.borrow_mut(),
+ &path,
+ mode,
+ Some(&write_open_options(create, append)),
+ "Deno.writeFile()",
+ )?;
+ let write_future = tokio::task::spawn_blocking(move || {
+ write_file(&path, open_options, mode, data)
+ });
+ if let Some(cancel_handle) = cancel_handle {
+ write_future.or_cancel(cancel_handle).await???;
+ } else {
+ write_future.await??;
+ }
+ Ok(())
+}
+
+#[op]
+async fn op_readfile_async(
+ state: Rc>,
+ path: String,
+ cancel_rid: Option,
+) -> Result {
+ {
+ let path = Path::new(&path);
+ let mut state = state.borrow_mut();
+ state
+ .borrow_mut::()
+ .read
+ .check(path, Some("Deno.readFile()"))?;
+ }
+ let fut = tokio::task::spawn_blocking(move || {
+ let path = Path::new(&path);
+ Ok(std::fs::read(path).map(ZeroCopyBuf::from)?)
+ });
+ if let Some(cancel_rid) = cancel_rid {
+ let cancel_handle = state
+ .borrow_mut()
+ .resource_table
+ .get::(cancel_rid);
+ if let Ok(cancel_handle) = cancel_handle {
+ return fut.or_cancel(cancel_handle).await??;
+ }
+ }
+ fut.await?
+}
diff --git a/runtime/ops/fs.rs b/runtime/ops/fs.rs
index 9b0737fe95426e..d67ae7cc0430b6 100644
--- a/runtime/ops/fs.rs
+++ b/runtime/ops/fs.rs
@@ -12,6 +12,7 @@ use deno_core::CancelFuture;
use deno_core::CancelHandle;
use deno_core::ZeroCopyBuf;
+use crate::ops::asyncfs;
use deno_core::Extension;
use deno_core::OpState;
use deno_core::ResourceId;
@@ -48,7 +49,7 @@ pub fn init() -> Extension {
op_open_sync::decl(),
op_open_async::decl(),
op_write_file_sync::decl(),
- op_write_file_async::decl(),
+ asyncfs::op_write_file_async::decl(),
op_seek_sync::decl(),
op_seek_async::decl(),
op_fdatasync_sync::decl(),
@@ -102,7 +103,7 @@ pub fn init() -> Extension {
op_utime_async::decl(),
op_readfile_sync::decl(),
op_readfile_text_sync::decl(),
- op_readfile_async::decl(),
+ asyncfs::op_readfile_async::decl(),
op_readfile_text_async::decl(),
])
.build()
@@ -112,16 +113,16 @@ pub fn init() -> Extension {
#[serde(rename_all = "camelCase")]
#[serde(default)]
pub struct OpenOptions {
- read: bool,
- write: bool,
- create: bool,
- truncate: bool,
- append: bool,
- create_new: bool,
+ pub read: bool,
+ pub write: bool,
+ pub create: bool,
+ pub truncate: bool,
+ pub append: bool,
+ pub create_new: bool,
}
#[inline]
-fn open_helper(
+pub(crate) fn open_helper(
state: &mut OpState,
path: &str,
mode: Option,
@@ -222,7 +223,7 @@ async fn op_open_async(
}
#[inline]
-fn write_open_options(create: bool, append: bool) -> OpenOptions {
+pub(crate) fn write_open_options(create: bool, append: bool) -> OpenOptions {
OpenOptions {
read: false,
write: true,
@@ -252,43 +253,7 @@ fn op_write_file_sync(
write_file(&path, open_options, mode, data)
}
-#[op]
-async fn op_write_file_async(
- state: Rc>,
- path: String,
- mode: Option,
- append: bool,
- create: bool,
- data: ZeroCopyBuf,
- cancel_rid: Option,
-) -> Result<(), AnyError> {
- let cancel_handle = match cancel_rid {
- Some(cancel_rid) => state
- .borrow_mut()
- .resource_table
- .get::(cancel_rid)
- .ok(),
- None => None,
- };
- let (path, open_options) = open_helper(
- &mut *state.borrow_mut(),
- &path,
- mode,
- Some(&write_open_options(create, append)),
- "Deno.writeFile()",
- )?;
- let write_future = tokio::task::spawn_blocking(move || {
- write_file(&path, open_options, mode, data)
- });
- if let Some(cancel_handle) = cancel_handle {
- write_future.or_cancel(cancel_handle).await???;
- } else {
- write_future.await??;
- }
- Ok(())
-}
-
-fn write_file(
+pub(crate) fn write_file(
path: &Path,
open_options: std::fs::OpenOptions,
_mode: Option,
@@ -2040,36 +2005,6 @@ fn op_readfile_text_sync(
Ok(string_from_utf8_lossy(std::fs::read(path)?))
}
-#[op]
-async fn op_readfile_async(
- state: Rc>,
- path: String,
- cancel_rid: Option,
-) -> Result {
- {
- let path = Path::new(&path);
- let mut state = state.borrow_mut();
- state
- .borrow_mut::()
- .read
- .check(path, Some("Deno.readFile()"))?;
- }
- let fut = tokio::task::spawn_blocking(move || {
- let path = Path::new(&path);
- Ok(std::fs::read(path).map(ZeroCopyBuf::from)?)
- });
- if let Some(cancel_rid) = cancel_rid {
- let cancel_handle = state
- .borrow_mut()
- .resource_table
- .get::(cancel_rid);
- if let Ok(cancel_handle) = cancel_handle {
- return fut.or_cancel(cancel_handle).await??;
- }
- }
- fut.await?
-}
-
#[op]
async fn op_readfile_text_async(
state: Rc>,
diff --git a/runtime/ops/mod.rs b/runtime/ops/mod.rs
index 526c36d6305afc..12bdd1944ff667 100644
--- a/runtime/ops/mod.rs
+++ b/runtime/ops/mod.rs
@@ -1,5 +1,6 @@
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
+mod asyncfs;
pub mod fs;
pub mod fs_events;
pub mod http;
diff --git a/runtime/tokio_util.rs b/runtime/tokio_util.rs
index 52888abe45b641..24ae3cd6f8d7fc 100644
--- a/runtime/tokio_util.rs
+++ b/runtime/tokio_util.rs
@@ -14,6 +14,7 @@ pub fn create_basic_runtime() -> tokio::runtime::Runtime {
.unwrap()
}
+#[cfg(not(feature = "enable_iouring"))]
pub fn run_local(future: F) -> R
where
F: std::future::Future