我有一个
类型的对象Arc<RwLock<SessionData>>
我有一个方法应该对SessionData
fn some_method(session: ...)
我正在使用Rocket(Rust的Web框架),我不能直接调用该方法,因为它是由Rocket调用的。但是,我可以为它提供一个实现,该实现创建一个将传递给处理程序的对象。看起来有点像这样:
impl<'a, 'r> request::FromRequest<'a, 'r> for SomeType {
type Error = ();
fn from_request(request: &'a request::Request<'r>) -> request::Outcome<Self, Self::Error> {
// return object here
}
}
我想避免直接返回RwLock
,因为我希望处理程序将一个已锁定的对象传递给它。但是,我无法返回引用或RwLockReadGuard
,因为它们都依赖于RwLock
,这将超出范围。
相反,我正在尝试创建一种包含Arc<RwLock<SessionData>>
的自足类型,包含此锁的锁定保护,并解析为SessionData
对象。
到目前为止,我已经尝试了以下几种组合:
Session
和Arc<RwLock<SessionData>>
RwLockReadGuard<SessionData>
对象
Arc<RwLock<SessionData>>
和RwLockReadGuardRef<SessionData>
的对象。OwnedHandle
类型的对象。然而,我无法做我想做的事情,遇到各种终身借贷问题等等。
是否可以创建一种自包含的“Handle”类对象,它包含锁定和锁定到它所指向的对象的锁定?
这与How to return reference to a sub-value of a value that is under a mutex?中描述的情况类似但略有不同。在那里,MutexGuardRef
内部取决于Mutex
,如果Mutex
(或MyStruct
)超出范围,则不能存在。为了实现类似的行为,我必须传递一个包含我的RwLock
的结构,然后在方法内部进行锁定。这很好,但我想知道我是否可以再向前迈一步,并传递一个既强独立的结构,又作为 RwLockGuard
,避免需要手动锁定。
基本上,我想将RwLock
从客户端锁定到值的提供者。
答案 0 :(得分:5)
如Why can't I store a value and a reference to that value in the same struct?所述,Rental crate在某些情况下允许自引用结构。
#[macro_use]
extern crate rental;
use std::sync::{Arc, RwLock};
struct SessionData;
impl SessionData {
fn hello(&self) -> u8 { 42 }
}
rental! {
mod owning_lock {
use std::sync::{Arc, RwLock, RwLockReadGuard};
#[rental(deref_suffix)]
pub struct OwningReadGuard<T>
where
T: 'static,
{
lock: Arc<RwLock<T>>,
guard: RwLockReadGuard<'lock, T>,
}
}
}
use owning_lock::OwningReadGuard;
fn owning_lock(session: Arc<RwLock<SessionData>>) -> OwningReadGuard<SessionData> {
OwningReadGuard::new(session, |s| s.read().unwrap())
}
fn main() {
let session = Arc::new(RwLock::new(SessionData));
let lock = owning_lock(session.clone());
println!("{}", lock.hello());
assert!(session.try_read().is_ok());
assert!(session.try_write().is_err());
drop(lock);
assert!(session.try_write().is_ok());
}
另见: