如何解决默认情况下取消引用 Arc<RwLock<T>> 以返回 RwLockReadGuard<T>
我有 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)]
编写了上述包装器。
大多数时候我从 T
读取值 Arc<RwLock<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()
相同的方式工作。但是编译器对返回局部变量的引用并不满意。有没有可能通过某种终生魔法或其他变通方法来实现?
解决方法
通过设计取消引用应该只解析指向被指点者的智能指针,参见例如Rust API Guidelines。在 MutexGuard
中获得像 RwLockReadGuard
或 Deref
这样的同步保护肯定超出了这个准则,可能会导致细微的错误。 IE。您可以在不显式调用 lock()
、read()
或 write()
的情况下获得资源的隐式锁定,因为它隐藏在解析方法时隐式调用的 Deref
impl 中打电话。
至于推理为什么这是不可能的:Deref
的返回类型是一个引用,因此您需要返回一些可以从 {{1} 变成引用的东西}. deref()
是您在 RwLockReadGuard
范围内创建的值,因此它被丢弃在范围的末尾,这反过来意味着您不能分发对它的引用。
有时将您需要用 deref()
内的值包装在函数内的值是符合人体工程学的,即如果它是一个 RwLock
有时会被写入但大多数时候您只是想阅读它,定义一些方便的方法如下:
String
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。