mirror of
https://github.com/denoland/deno.git
synced 2025-09-29 05:34:49 +00:00
feat(core): sync io ops in core (#18603)
This commit adds op_read_sync and op_write_sync to core. These ops are similar to op_read and op_write, but they are synchronous. Just like the async ops, they operate on generic `deno_core::Resource` objects. These now have new `read_byob_sync` and `write_sync` methods, with default implementations throwing "NotSupported" errors, just like the async counterparts. There are no `write_all` or `read` equivalents, because the optimizations they unlock are not useful in synchronous contexts.
This commit is contained in:
parent
ee15b49845
commit
36e8c8dfd7
6 changed files with 77 additions and 54 deletions
|
@ -412,6 +412,8 @@
|
||||||
readAll: opAsync.bind(null, "op_read_all"),
|
readAll: opAsync.bind(null, "op_read_all"),
|
||||||
write: opAsync.bind(null, "op_write"),
|
write: opAsync.bind(null, "op_write"),
|
||||||
writeAll: opAsync.bind(null, "op_write_all"),
|
writeAll: opAsync.bind(null, "op_write_all"),
|
||||||
|
readSync: (rid, buffer) => ops.op_read_sync(rid, buffer),
|
||||||
|
writeSync: (rid, buffer) => ops.op_write_sync(rid, buffer),
|
||||||
shutdown: opAsync.bind(null, "op_shutdown"),
|
shutdown: opAsync.bind(null, "op_shutdown"),
|
||||||
print: (msg, isErr) => ops.op_print(msg, isErr),
|
print: (msg, isErr) => ops.op_print(msg, isErr),
|
||||||
setMacrotaskCallback: (fn) => ops.op_set_macrotask_callback(fn),
|
setMacrotaskCallback: (fn) => ops.op_set_macrotask_callback(fn),
|
||||||
|
|
10
core/lib.deno_core.d.ts
vendored
10
core/lib.deno_core.d.ts
vendored
|
@ -60,6 +60,16 @@ declare namespace Deno {
|
||||||
*/
|
*/
|
||||||
function writeAll(rid: number, buf: Uint8Array): Promise<void>;
|
function writeAll(rid: number, buf: Uint8Array): Promise<void>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Synchronously read from a (stream) resource that implements readSync().
|
||||||
|
*/
|
||||||
|
function readSync(rid: number, buf: Uint8Array): number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Synchronously write to a (stream) resource that implements writeSync().
|
||||||
|
*/
|
||||||
|
function writeSync(rid: number, buf: Uint8Array): number;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Print a message to stdout or stderr
|
* Print a message to stdout or stderr
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -33,6 +33,8 @@ crate::extension!(
|
||||||
op_read,
|
op_read,
|
||||||
op_read_all,
|
op_read_all,
|
||||||
op_write,
|
op_write,
|
||||||
|
op_read_sync,
|
||||||
|
op_write_sync,
|
||||||
op_write_all,
|
op_write_all,
|
||||||
op_shutdown,
|
op_shutdown,
|
||||||
op_metrics,
|
op_metrics,
|
||||||
|
@ -279,6 +281,27 @@ async fn op_write(
|
||||||
Ok(resp.nwritten() as u32)
|
Ok(resp.nwritten() as u32)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[op(fast)]
|
||||||
|
fn op_read_sync(
|
||||||
|
state: &mut OpState,
|
||||||
|
rid: ResourceId,
|
||||||
|
data: &mut [u8],
|
||||||
|
) -> Result<u32, Error> {
|
||||||
|
let resource = state.resource_table.get_any(rid)?;
|
||||||
|
resource.read_byob_sync(data).map(|n| n as u32)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[op]
|
||||||
|
fn op_write_sync(
|
||||||
|
state: &mut OpState,
|
||||||
|
rid: ResourceId,
|
||||||
|
data: &[u8],
|
||||||
|
) -> Result<u32, Error> {
|
||||||
|
let resource = state.resource_table.get_any(rid)?;
|
||||||
|
let nwritten = resource.write_sync(data)?;
|
||||||
|
Ok(nwritten as u32)
|
||||||
|
}
|
||||||
|
|
||||||
#[op]
|
#[op]
|
||||||
async fn op_write_all(
|
async fn op_write_all(
|
||||||
state: Rc<RefCell<OpState>>,
|
state: Rc<RefCell<OpState>>,
|
||||||
|
|
|
@ -154,6 +154,18 @@ pub trait Resource: Any + 'static {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The same as [`read_byob()`][Resource::read_byob], but synchronous.
|
||||||
|
fn read_byob_sync(&self, data: &mut [u8]) -> Result<usize, Error> {
|
||||||
|
_ = data;
|
||||||
|
Err(not_supported())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The same as [`write()`][Resource::write], but synchronous.
|
||||||
|
fn write_sync(&self, data: &[u8]) -> Result<usize, Error> {
|
||||||
|
_ = data;
|
||||||
|
Err(not_supported())
|
||||||
|
}
|
||||||
|
|
||||||
/// The shutdown method can be used to asynchronously close the resource. It
|
/// The shutdown method can be used to asynchronously close the resource. It
|
||||||
/// is not automatically called when the resource is dropped or closed.
|
/// is not automatically called when the resource is dropped or closed.
|
||||||
///
|
///
|
||||||
|
|
|
@ -93,27 +93,19 @@ function* iterSync(
|
||||||
}
|
}
|
||||||
|
|
||||||
function readSync(rid, buffer) {
|
function readSync(rid, buffer) {
|
||||||
if (buffer.length === 0) {
|
if (buffer.length === 0) return 0;
|
||||||
return 0;
|
const nread = core.readSync(rid, buffer);
|
||||||
}
|
|
||||||
|
|
||||||
const nread = ops.op_read_sync(rid, buffer);
|
|
||||||
|
|
||||||
return nread === 0 ? null : nread;
|
return nread === 0 ? null : nread;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function read(rid, buffer) {
|
async function read(rid, buffer) {
|
||||||
if (buffer.length === 0) {
|
if (buffer.length === 0) return 0;
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
const nread = await core.read(rid, buffer);
|
const nread = await core.read(rid, buffer);
|
||||||
|
|
||||||
return nread === 0 ? null : nread;
|
return nread === 0 ? null : nread;
|
||||||
}
|
}
|
||||||
|
|
||||||
function writeSync(rid, data) {
|
function writeSync(rid, data) {
|
||||||
return ops.op_write_sync(rid, data);
|
return core.writeSync(rid, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
function write(rid, data) {
|
function write(rid, data) {
|
||||||
|
|
|
@ -78,7 +78,6 @@ pub static STDERR_HANDLE: Lazy<StdFile> = Lazy::new(|| {
|
||||||
|
|
||||||
deno_core::extension!(deno_io,
|
deno_core::extension!(deno_io,
|
||||||
deps = [ deno_web ],
|
deps = [ deno_web ],
|
||||||
ops = [op_read_sync, op_write_sync],
|
|
||||||
esm = [ "12_io.js" ],
|
esm = [ "12_io.js" ],
|
||||||
options = {
|
options = {
|
||||||
stdio: Option<Stdio>,
|
stdio: Option<Stdio>,
|
||||||
|
@ -454,7 +453,7 @@ impl StdFileResource {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn with_inner_and_metadata<TResult>(
|
fn with_inner_and_metadata<TResult>(
|
||||||
self: Rc<Self>,
|
&self,
|
||||||
action: impl FnOnce(
|
action: impl FnOnce(
|
||||||
&mut StdFileResourceInner,
|
&mut StdFileResourceInner,
|
||||||
&Arc<Mutex<FileMetadata>>,
|
&Arc<Mutex<FileMetadata>>,
|
||||||
|
@ -471,10 +470,7 @@ impl StdFileResource {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn with_inner_blocking_task<F, R: Send + 'static>(
|
async fn with_inner_blocking_task<F, R: Send + 'static>(&self, action: F) -> R
|
||||||
self: Rc<Self>,
|
|
||||||
action: F,
|
|
||||||
) -> R
|
|
||||||
where
|
where
|
||||||
F: FnOnce(&mut StdFileResourceInner) -> R + Send + 'static,
|
F: FnOnce(&mut StdFileResourceInner) -> R + Send + 'static,
|
||||||
{
|
{
|
||||||
|
@ -540,6 +536,14 @@ impl StdFileResource {
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn read_byob_sync(&self, buf: &mut [u8]) -> Result<usize, AnyError> {
|
||||||
|
self.with_inner_and_metadata(|inner, _| inner.read(buf).map_err(Into::into))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_sync(&self, data: &[u8]) -> Result<usize, AnyError> {
|
||||||
|
self.with_inner_and_metadata(|inner, _| inner.write_and_maybe_flush(data))
|
||||||
|
}
|
||||||
|
|
||||||
fn with_resource<F, R>(
|
fn with_resource<F, R>(
|
||||||
state: &mut OpState,
|
state: &mut OpState,
|
||||||
rid: ResourceId,
|
rid: ResourceId,
|
||||||
|
@ -632,7 +636,7 @@ impl Resource for StdFileResource {
|
||||||
Box::pin(async move {
|
Box::pin(async move {
|
||||||
let vec = vec![0; limit];
|
let vec = vec![0; limit];
|
||||||
let buf = BufMutView::from(vec);
|
let buf = BufMutView::from(vec);
|
||||||
let (nread, buf) = self.read_byob(buf).await?;
|
let (nread, buf) = StdFileResource::read_byob(self, buf).await?;
|
||||||
let mut vec = buf.unwrap_vec();
|
let mut vec = buf.unwrap_vec();
|
||||||
if vec.len() != nread {
|
if vec.len() != nread {
|
||||||
vec.truncate(nread);
|
vec.truncate(nread);
|
||||||
|
@ -645,17 +649,29 @@ impl Resource for StdFileResource {
|
||||||
self: Rc<Self>,
|
self: Rc<Self>,
|
||||||
buf: deno_core::BufMutView,
|
buf: deno_core::BufMutView,
|
||||||
) -> AsyncResult<(usize, deno_core::BufMutView)> {
|
) -> AsyncResult<(usize, deno_core::BufMutView)> {
|
||||||
Box::pin(self.read_byob(buf))
|
Box::pin(StdFileResource::read_byob(self, buf))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write(
|
fn write(
|
||||||
self: Rc<Self>,
|
self: Rc<Self>,
|
||||||
view: deno_core::BufView,
|
view: deno_core::BufView,
|
||||||
) -> AsyncResult<deno_core::WriteOutcome> {
|
) -> AsyncResult<deno_core::WriteOutcome> {
|
||||||
Box::pin(self.write(view))
|
Box::pin(StdFileResource::write(self, view))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_all(self: Rc<Self>, view: deno_core::BufView) -> AsyncResult<()> {
|
fn write_all(self: Rc<Self>, view: deno_core::BufView) -> AsyncResult<()> {
|
||||||
Box::pin(self.write_all(view))
|
Box::pin(StdFileResource::write_all(self, view))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_sync(&self, data: &[u8]) -> Result<usize, deno_core::anyhow::Error> {
|
||||||
|
StdFileResource::write_sync(self, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_byob_sync(
|
||||||
|
&self,
|
||||||
|
data: &mut [u8],
|
||||||
|
) -> Result<usize, deno_core::anyhow::Error> {
|
||||||
|
StdFileResource::read_byob_sync(self, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
|
@ -684,35 +700,3 @@ pub fn op_print(
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[op(fast)]
|
|
||||||
fn op_read_sync(
|
|
||||||
state: &mut OpState,
|
|
||||||
rid: u32,
|
|
||||||
buf: &mut [u8],
|
|
||||||
) -> Result<u32, AnyError> {
|
|
||||||
StdFileResource::with_resource(state, rid, move |resource| {
|
|
||||||
resource.with_inner_and_metadata(|inner, _| {
|
|
||||||
inner
|
|
||||||
.read(buf)
|
|
||||||
.map(|n: usize| n as u32)
|
|
||||||
.map_err(AnyError::from)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
#[op(fast)]
|
|
||||||
fn op_write_sync(
|
|
||||||
state: &mut OpState,
|
|
||||||
rid: u32,
|
|
||||||
buf: &mut [u8],
|
|
||||||
) -> Result<u32, AnyError> {
|
|
||||||
StdFileResource::with_resource(state, rid, move |resource| {
|
|
||||||
resource.with_inner_and_metadata(|inner, _| {
|
|
||||||
inner
|
|
||||||
.write_and_maybe_flush(buf)
|
|
||||||
.map(|nwritten: usize| nwritten as u32)
|
|
||||||
.map_err(AnyError::from)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue