Last active
December 2, 2024 00:30
-
-
Save jberkenbilt/d8a5a002d79c769574f2e11824fe6e2d to your computer and use it in GitHub Desktop.
Go to Rust 05: controller diff
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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