Last active
January 7, 2022 03:54
-
-
Save mxgrey/939e7af24202c294a63f852eb0d810aa to your computer and use it in GitHub Desktop.
Rough draft of idea for safely blocking ros2_rust client
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
// The code in this file should be treated as a rough sketch. It probably contains errors, and it is definitely missing | |
// large chunks of implementation. | |
struct Executor { | |
// ... details ... | |
} | |
enum SpinError { | |
/// The spinning has timed out | |
Timeout, | |
/// The client you provided does not belong to the callback group of this executor | |
WrongGroup, | |
/// You are waiting on a spin result from inside of a callback in this same callback group | |
Recursive | |
} | |
impl Executor { | |
fn is_in_group<ST>(&self, client: &Client<ST>) -> bool { | |
// TODO: Check if client belongs to the callback group of this executor | |
} | |
fn ensure_spinning(&self) -> SpinAssurance { | |
// TODO: If the executor is not spinning, create a thread for the executor to perform its spinning in. | |
// If the executor is already spinning, do nothing. | |
// TODO: SpinAssurance would be some type that does reference counting. When the SpinAssurance instance gets | |
// dropped, the spinning thread gets terminated. | |
} | |
fn spin(&self) { | |
let spin_assurance = self.ensure_spinning(); | |
// TODO: Block the thread while the context is okay | |
} | |
async fn spin_until_service_available<ST>( | |
&self, | |
&client: Client<ST>, | |
timeout: Option<std::time::Duration>) | |
-> Result<(), SpinError> | |
where ST: ServiceType { | |
if !self.is_in_group(client) { | |
return SpinError::WrongGroup; | |
} | |
let spin_assurance = self.ensure_spinning(); | |
if std::thread::current().id() == self.spin_thread { | |
return SpinError::Recursive; | |
} | |
// TODO: Have this function wait on some condition variable which watches whether a service has become available | |
} | |
async fn spin_until_response_arrives<ST>( | |
&self, | |
&mut client: Client<ST>, | |
request: ST::Request, | |
timeout: Option<std::time::Duration>) | |
-> Result<ST::Response, Timeout> | |
where ST: ServiceType { | |
if !self.is_in_group(client) { | |
return SpinError::WrongGroup; | |
} | |
let spin_assurance = self.ensure_spinning(); | |
if std::thread::current().id() == self.spin_thread { | |
return SpinError::Recursive; | |
} | |
self.spin_until_service_available(client).await; | |
let (completer, promise) = std::futures::promise::<ST::Response>(); | |
client.send_request( | |
request, | |
move |response: ST::Response| { | |
completer.complete(response); | |
} | |
// TODO: Await on promise, but give up if we reach the timeout | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment