I have a thread that periodically calls a callback function. Depending on the state, the callback function shall acquire an RwLock
of a resource shared with other threads and keep the resource locked even beyond the scope of the callback function. It shall then again depending on the state release the resource again in a later callback cycle.
My idea was to put an Option<RwLockReadGuard<T>>
into a struct which would be None
when the resource is not locked and Some(RwLockReadGuard<T>)
when the resource is locked.
Unfortunately, I can't make this work. I have to set up the struct which contains the Option<RwLockReadGuard<T>>
outside the thread of the callback function. Even though at the time the struct is moved into the thread the Option
is None
, the compiler won't let me pass the option because the trait bound ``std::sync::RwLockReadGuard<'_, T>: std::marker::Send`` is not satisfied
.
Maybe some code. I hope it's self-explaining enough.
use std::thread;
use std::sync::{Arc, RwLock, RwLockReadGuard};
struct Handler<'a> {
resource: Arc<RwLock<String>>,
locked_resource: Option<RwLockReadGuard<'a, String>>,
counter: usize,
}
impl<'a> Handler<'a> {
fn callback(&'a mut self) {
println!("Callback {}", self.counter);
if self.counter == 0 {
println!("Locking resource");
let res = self.resource.read().unwrap();
self.locked_resource = Some(res);
}
self.counter += 1;
if self.counter == 100 {
println!("Releasing resource");
self.locked_resource = None;
}
if self.counter == 200 {
self.counter = 0;
}
}
}
fn main() {
let resource = Arc::new(RwLock::new("foo".to_string()));
let handler = Handler {
resource: resource.clone(),
locked_resource: None,
counter: 0
};
// This gives E0277
let thread = thread::spawn( move || {
loop {
handler.callback();
}
});
}