Skip to content

Instantly share code, notes, and snippets.

@jberkenbilt
Last active December 2, 2024 00:30
Show Gist options
  • Save jberkenbilt/d8a5a002d79c769574f2e11824fe6e2d to your computer and use it in GitHub Desktop.
Save jberkenbilt/d8a5a002d79c769574f2e11824fe6e2d to your computer and use it in GitHub Desktop.
Go to Rust 05: controller diff
diff -ur --ex 04-generic-async-rwlock-first-try/controller/src/lib.rs 05-final/controller/src/lib.rs
--- 04-generic-async-rwlock-first-try/controller/src/lib.rs 2024-12-01 16:36:03
+++ 05-final/controller/src/lib.rs 2024-12-01 19:26:01
@@ -2,8 +2,11 @@
//! implementation pretends to make network calls and accesses locked
//! data. It is wrapped by a function-based API that operates a
//! singleton.
-use base::AsyncRwLock;
+use base::{AsyncRwLock, LockBox, Runtime};
+use implbox::ImplBox;
use std::error::Error;
+use std::marker::PhantomData;
+use std::ops::DerefMut;
#[derive(Default)]
struct ReqData {
@@ -11,18 +14,32 @@
last_path: String,
}
-#[derive(Default)]
-pub struct Controller {
- req_data: Box<impl AsyncRwLock<ReqData>>,
+pub struct Controller<RuntimeT: Runtime> {
+ req_data: ImplBox<LockBox<ReqData>>,
+ _r: PhantomData<RuntimeT>,
}
-impl Controller {
+impl<RuntimeT: Runtime> Default for Controller<RuntimeT> {
+ fn default() -> Self {
+ Self {
+ req_data: RuntimeT::box_lock(Default::default()),
+ _r: Default::default(),
+ }
+ }
+}
+
+impl<RuntimeT: Runtime> Controller<RuntimeT> {
pub fn new() -> Self {
Default::default()
}
+ fn req_data(&self) -> &(impl AsyncRwLock<ReqData> + '_) {
+ RuntimeT::unbox_lock(&self.req_data)
+ }
+
async fn request(&self, path: &str) -> Result<(), Box<dyn Error + Sync + Send>> {
- let mut ref_data = self.req_data.write().await;
+ let mut lock = self.req_data().write().await;
+ let ref_data: &mut ReqData = lock.deref_mut();
ref_data.seq += 1;
// A real implementation would make a network call here. Call await to make this
// non-trivially async.
@@ -39,23 +56,24 @@
return Err("sorry, not that one".into());
}
self.request(&format!("one?val={val}")).await?;
- Ok(self.req_data.read().await.seq)
+ Ok(self.req_data().read().await.seq)
}
/// Send a request and return the path of the request.
pub async fn two(&self, val: &str) -> Result<String, Box<dyn Error + Sync + Send>> {
self.request(&format!("two?val={val}")).await?;
- Ok(self.req_data.read().await.last_path.clone())
+ Ok(self.req_data().read().await.last_path.clone())
}
}
#[cfg(test)]
mod tests {
use super::*;
+ use runtime_tokio::TokioRuntime;
#[tokio::test]
async fn test_basic() {
- let c = Controller::new();
+ let c = Controller::<TokioRuntime>::new();
assert_eq!(c.one(5).await.unwrap(), 1);
assert_eq!(
c.one(3).await.err().unwrap().to_string(),
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment