Hello World works
This commit is contained in:
@@ -13,11 +13,11 @@ async-once-cell = "0.5.4"
|
||||
bound = "0.6.0"
|
||||
derive_destructure = "1.0.0"
|
||||
dyn-clone = "1.0.20"
|
||||
futures = { version = "0.3.31", default-features = false, features = [
|
||||
"std",
|
||||
"async-await",
|
||||
futures = { version = "0.3.32", default-features = false, features = [
|
||||
"std",
|
||||
"async-await",
|
||||
] }
|
||||
hashbrown = "0.16.1"
|
||||
hashbrown = "0.17.0"
|
||||
itertools = "0.14.0"
|
||||
lazy_static = "1.5.0"
|
||||
never = "0.1.0"
|
||||
@@ -25,14 +25,14 @@ num-traits = "0.2.19"
|
||||
orchid-api = { version = "0.1.0", path = "../orchid-api" }
|
||||
orchid-api-derive = { version = "0.1.0", path = "../orchid-api-derive" }
|
||||
orchid-api-traits = { version = "0.1.0", path = "../orchid-api-traits" }
|
||||
ordered-float = "5.1.0"
|
||||
regex = "1.12.2"
|
||||
rust-embed = "8.9.0"
|
||||
ordered-float = "5.3.0"
|
||||
regex = "1.12.3"
|
||||
rust-embed = "8.11.0"
|
||||
substack = "1.1.1"
|
||||
trait-set = "0.3.0"
|
||||
task-local = "0.1.0"
|
||||
task-local = "0.1.1"
|
||||
|
||||
[dev-dependencies]
|
||||
futures = "0.3.31"
|
||||
rand = "0.10.0"
|
||||
futures = "0.3.32"
|
||||
rand = "0.10.1"
|
||||
rand_chacha = "0.10.0"
|
||||
|
||||
@@ -17,7 +17,7 @@ use futures::{
|
||||
use hashbrown::HashMap;
|
||||
use orchid_api_traits::{Decode, Encode, Request, UnderRoot};
|
||||
use orchid_async_utils::debug::{PanicOnDrop, assert_no_drop};
|
||||
use orchid_async_utils::{cancel_cleanup, local_set, to_task};
|
||||
use orchid_async_utils::{Handle, cancel_cleanup, local_set, to_task};
|
||||
|
||||
use crate::{clone, finish_or_stash, stash, with_stash};
|
||||
|
||||
@@ -293,29 +293,35 @@ type IoGuard<T> = Bound<MutexGuard<'static, Pin<Box<T>>>, IoLock<T>>;
|
||||
|
||||
/// An incoming request. This holds a lock on the ingress channel.
|
||||
pub struct IoReqReader {
|
||||
prefix: u64,
|
||||
id: u64,
|
||||
read: IoGuard<dyn AsyncRead>,
|
||||
o: Rc<Mutex<IoRef<dyn AsyncWrite>>>,
|
||||
requests: Rc<RefCell<HashMap<u64, Handle<io::Result<()>>>>>,
|
||||
}
|
||||
impl ReqReader for IoReqReader {
|
||||
fn reader(&mut self) -> Pin<&mut dyn AsyncRead> { self.read.as_mut() }
|
||||
fn finish(self: Box<Self>) -> LocalBoxFuture<'static, Box<dyn ReqHandle>> {
|
||||
Box::pin(async {
|
||||
Box::new(IoReqHandle { prefix: self.prefix, write: self.o }) as Box<dyn ReqHandle>
|
||||
Box::new(IoReqHandle { id: self.id, write: self.o, requests: self.requests })
|
||||
as Box<dyn ReqHandle>
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub struct IoReqHandle {
|
||||
prefix: u64,
|
||||
id: u64,
|
||||
write: IoLock<dyn AsyncWrite>,
|
||||
requests: Rc<RefCell<HashMap<u64, Handle<io::Result<()>>>>>,
|
||||
}
|
||||
impl ReqHandle for IoReqHandle {
|
||||
fn start_reply(self: Box<Self>) -> LocalBoxFuture<'static, io::Result<Box<dyn RepWriter>>> {
|
||||
let write = self.write.clone();
|
||||
Box::pin(async move {
|
||||
let mut write = Bound::async_new(write, |l| l.lock()).await;
|
||||
self.prefix.encode(write.as_mut()).await?;
|
||||
self.requests.borrow_mut().remove(&self.id);
|
||||
let mut prefix = self.id.to_be_bytes();
|
||||
prefix[0] = 0x01;
|
||||
write.write_all(&prefix).await?;
|
||||
Ok(Box::new(IoRepWriter { write }) as Box<dyn RepWriter>)
|
||||
})
|
||||
}
|
||||
@@ -552,8 +558,8 @@ impl IoCommServer {
|
||||
}
|
||||
});
|
||||
|
||||
let running_requests = RefCell::new(HashMap::new());
|
||||
let (mut task_pool, fork_future) = local_set();
|
||||
let running_requests = Rc::new(RefCell::new(HashMap::new()));
|
||||
let (task_pool, fork_future) = local_set();
|
||||
let mut fork_stream = pin!(fork_future.into_stream());
|
||||
let mut pending_replies = HashMap::new();
|
||||
'body: {
|
||||
@@ -577,7 +583,7 @@ impl IoCommServer {
|
||||
// ID 0 is reserved for single-fire notifications
|
||||
Ok(Event::Input(0, read)) => {
|
||||
let notif = ¬if;
|
||||
task_pool.spawn(notif(Box::new(IoMsgReader { _pd: PhantomData, read }))).await.unwrap();
|
||||
task_pool.spawn(notif(Box::new(IoMsgReader { _pd: PhantomData, read })))
|
||||
},
|
||||
// non-zero IDs are associated with requests
|
||||
Ok(Event::Input(id, read)) => {
|
||||
@@ -588,21 +594,16 @@ impl IoCommServer {
|
||||
match discr {
|
||||
// request
|
||||
0x00 => {
|
||||
let (o, req, reqs) = (o.clone(), &req, &running_requests);
|
||||
task_pool
|
||||
.spawn(async move {
|
||||
id_bytes[0] = 0x01;
|
||||
let prefix = u64::from_be_bytes(id_bytes);
|
||||
let reader = Box::new(IoReqReader { prefix, read, o });
|
||||
let (fut, handle) = to_task(async { req(reader).await.map(|Receipt| ()) });
|
||||
reqs.borrow_mut().insert(id, handle);
|
||||
with_stash(fut).await;
|
||||
// during this await the read guard is released and thus we may receive a
|
||||
// cancel notification from below
|
||||
Ok(())
|
||||
})
|
||||
.await
|
||||
.unwrap();
|
||||
let (o, req, reqs) = (o.clone(), &req, running_requests.clone());
|
||||
task_pool.spawn(async move {
|
||||
let reader = Box::new(IoReqReader { id, read, o, requests: reqs.clone() });
|
||||
let (fut, handle) = to_task(async { req(reader).await.map(|Receipt| ()) });
|
||||
reqs.borrow_mut().insert(id, handle);
|
||||
with_stash(fut).await;
|
||||
// during this await the read guard is released and thus we may receive a
|
||||
// cancel notification from below
|
||||
Ok(())
|
||||
});
|
||||
},
|
||||
// response
|
||||
0x01 => {
|
||||
@@ -619,21 +620,18 @@ impl IoCommServer {
|
||||
None => continue,
|
||||
};
|
||||
let (o, running_reqs) = (o.clone(), &running_requests);
|
||||
task_pool
|
||||
.spawn(async move {
|
||||
// if the request starts writing back before our abort arrives, we only
|
||||
// get this mutex once it's done
|
||||
let mut write = o.lock().await;
|
||||
// if the request is still in the store, the write didn't begin
|
||||
let Some(_) = running_reqs.borrow_mut().remove(&id) else { return Ok(()) };
|
||||
id_bytes[0] = 0x03;
|
||||
let cancel_code = u64::from_be_bytes(id_bytes);
|
||||
cancel_code.encode(write.as_mut()).await?;
|
||||
write.flush().await?;
|
||||
Ok(())
|
||||
})
|
||||
.await
|
||||
.unwrap();
|
||||
task_pool.spawn(async move {
|
||||
// if the request starts writing back before our abort arrives, we only
|
||||
// get this mutex once it's done
|
||||
let mut write = o.lock().await;
|
||||
// if the request is still in the store, the write didn't begin
|
||||
let Some(_) = running_reqs.borrow_mut().remove(&id) else { return Ok(()) };
|
||||
id_bytes[0] = 0x03;
|
||||
let cancel_code = u64::from_be_bytes(id_bytes);
|
||||
cancel_code.encode(write.as_mut()).await?;
|
||||
write.flush().await?;
|
||||
Ok(())
|
||||
});
|
||||
},
|
||||
// stub reply for cancelled request
|
||||
0x03 => {
|
||||
|
||||
@@ -1,17 +1,23 @@
|
||||
/// Cache a value in a [thread_local!]. Supports synchronous and asynchronous
|
||||
/// initializers
|
||||
///
|
||||
/// Synchronous use-case:
|
||||
/// ```
|
||||
/// use std::rc::Rc;
|
||||
/// #[macro_use]
|
||||
/// use orchid_base::tl_cache;
|
||||
/// let foo = tl_cache!(Rc<Vec<usize>>: Rc::new(vec![0; 1024]));
|
||||
/// ```
|
||||
///
|
||||
/// Asynchronous use-case:
|
||||
/// ```
|
||||
/// #[macro_use]
|
||||
/// use orchid_base::tl_cache;
|
||||
///
|
||||
/// // simple synchronous case
|
||||
/// let foo = tl_cache!(Rc<Vec<usize>>: vec![0; 1024]);
|
||||
/// async fn complex_operation(x: usize) -> usize { x + 1 }
|
||||
/// async {
|
||||
/// async fn complex_operation(x: usize) -> usize { x + 1 }
|
||||
/// // async case
|
||||
/// let bar = tl_cache!(async usize: complex_operation(0).await)
|
||||
/// }
|
||||
/// let bar = tl_cache!(async usize: complex_operation(0).await);
|
||||
/// };
|
||||
/// ```
|
||||
#[macro_export]
|
||||
macro_rules! tl_cache {
|
||||
|
||||
Reference in New Issue
Block a user