Вы можете сделать это с типом оболочки:
Детская площадка
use std::ops::{Deref, DerefMut, Drop};
use std::sync::{RwLock, RwLockWriteGuard};
type CleanupClosure<'a> = Fn(&mut RwLockWriteGuard<'a, Data>);
struct Data {
content: String,
}
impl Data {
fn change(&mut self, num: i32) {
println!("Changed to {}", num);
self.content = num.to_string();
}
}
struct RwLockWriteWrapper<'a, F: CleanupClosure<'a>>(RwLockWriteGuard<'a, Data>, F);
impl<'a, F: CleanupClosure<'a>> Deref for RwLockWriteWrapper<'a, F> {
type Target = RwLockWriteGuard<'a, Data>;
fn deref(&self) -> &RwLockWriteGuard<'a, Data> {
&self.0
}
}
impl<'a, F: CleanupClosure<'a>> DerefMut for RwLockWriteWrapper<'a, F> {
fn deref_mut(&mut self) -> &mut RwLockWriteGuard<'a, Data> {
&mut self.0
}
}
impl<'a, F: CleanupClosure<'a>> Drop for RwLockWriteWrapper<'a, F> {
fn drop(&mut self) {
println!("Cleaning up!");
self.1(&mut self.0)
}
}
fn main() {
let data: RwLock<Data> = RwLock::new(Data {
content: "Start".to_owned(),
});
do_something(&data);
do_something(&data);
}
fn do_something(data: &RwLock<Data>) {
// Write your own cleanup logic here
let mut state = RwLockWriteWrapper(data.write().unwrap(), |state| {
state.content = "Cleaned up".to_owned()
});
println!("do_something start: {}", state.content);
state.change(5);
println!("do_something after change: {}", state.content);
} // Automatically run cleanup here
Требуется не забывать оборачивать тип при вызове .write()
в теме. Вы можете обернуть RwLock
в другой тип, который также вернет RwLockWriteWrapper
, чтобы автоматизировать это.
Это становится довольно многословным, поэтому я нашел ящик, который подразумевает для вас черту разыскивания .
Я до сих пор не уверен, что означают замыкания, упомянутые вами в названии.