【发布时间】:2021-06-10 07:59:48
【问题描述】:
我有以下 Arc<RwLock<T>> 的包装器,我想取消它们以默认返回 RwLockReadGuard<T>。
use anyhow::{Result, bail};
use serde::{Deserialize, Serialize};
use std::ops::Deref;
use std::sync::{Arc, Mutex, RwLock, RwLockReadGuard, RwLockWriteGuard};
#[derive(Serialize, Deserialize, Debug, Clone, Default)]
pub struct ArcRwLock<T: Sized>(Arc<RwLock<T>>);
impl<T> ArcRwLock<T> {
pub fn new(data: T) -> Self {
ArcRwLock(Arc::new(RwLock::new(data)))
}
pub fn write(&self) -> Result<RwLockWriteGuard<T>> {
match self.0.try_write() {
Ok(x) => Ok(x),
Err(e) => {
bail!(
"RwLock cannot acquire writer lock, error: {}",
e.to_string()
)
}
}
}
pub fn read(&self) -> RwLockReadGuard<T> {
self.0.read().unwrap()
}
}
// impl<T: Sized> Deref for ArcRwLock<T> {
// type Target = RwLockReadGuard<T>;
// #[inline]
// fn deref(&self) -> &Self::Target {
// self.0.read().unwrap()
// }
// }
impl<T: PartialEq> PartialEq for ArcRwLock<T> {
fn eq(&self, other: &Self) -> bool {
if Arc::ptr_eq(&self.0, &other.0) && ::core::ptr::eq(&*self.0, &*other.0) {
true
} else {
*other.0.read().unwrap().deref() == *self.0.read().unwrap().deref()
}
}
}
我为PartialEq编写了上面的包装器,我需要一个父结构来正确#[derive(PartialEq)]。
大多数时候我从Arc<RwLock<T>> 读取值T,很少写入。
上述实现允许我使用以下方式读取/写入值:
some_arc_object.write()?.uuid = Uuid::new_v4();
let updated_uuid: T = some_arc_object.read().uuid;
// where uuid is a field of T
由于我大部分时间都在阅读属性,我想摆脱重复的.read(),并通过取消引用整个 Arc
let updated_uuid: T = some_arc_object.uuid;
// instead of having to add .read()
// let updated_uuid: T = some_arc_object.read().uuid;
我目前的谦虚尝试显示在上面的评论部分,试图让deref() 以与.read() 相同的方式工作。但是编译器对返回局部变量的引用并不满意。有没有可能通过一些终生的魔法或其他解决方法来实现它?
【问题讨论】: