代码之家  ›  专栏  ›  技术社区  ›  stimulate

使用隐式锁定将互斥锁/RwLock解除到内部对象

  •  0
  • stimulate  · 技术社区  · 3 年前

    我有一个结构 Obj 我还希望通过 Arc<RwLock<Obj>> 。我定义了 struct ObjRef(Arc<RwLock<Obj>>) 并希望调用的函数 Obj公司 在…上 ObjRef 不需要打电话 .read().unwrap() .write().unwrap() 每一次。( 对象引用 机具 Deref<Target=Arc<RwLock<Obj>> ,所以我只需要打电话 objRef.read().unwrap() )

    我可以实现 Obj公司 再次用于 对象引用 以这样的方式:

    impl ObjRef {
        fn foo(&self, arg: Arg) -> Ret {
            self.read().unwrap().foo(arg)
        }
    }
    

    但对每个函数都这样做会产生很多样板文件。

    实施 Deref<Target=Obj> 对于 对象引用 不起作用,因为 deref 实现将把引用返回到 RwReadLockGuard 对象返回者 。读取()。展开() 之后会被丢弃 德里夫 :

    impl Deref for ObjRef {
        type Target = Obj;
        fn deref(&self) -> &Self::Target {
            let guard: RwLockReadGuard<'_, Obj> = self.0.read().unwrap();
            &*guard // <- return reference to Obj referenced by guard
            // guard is dropped now, reference lifetime ends
        }
    }
    

    有没有办法打电话给 Obj公司 Api通过低模板实现在内部执行锁定?

    我正在考虑为Api引入一个trait,其中包含一个默认的Api实现和一个由trait用户实现的函数,以获取泛型 取消(&L);目标=目标(>); ,但这使Api受到一些限制,例如使用泛型参数将变得更加复杂。

    有没有更好的方法,可以让我 Obj公司 每次都没有显式调用锁定机制?

    0 回复  |  直到 3 年前
        1
  •  3
  •   Kevin Reid    3 年前

    不可能通过 Deref 因为 Deref::deref 始终返回普通引用。它的有效性必须仅取决于参数是否继续存在(借用检查器理解),而不取决于任何其他状态,如“锁定”。

    此外,向没有锁的接口添加锁通常是危险的,因为它可能会意外导致死锁,或者由于按顺序执行两个本应使用 仅有一个的 锁定。

    我建议你考虑做你喜欢的类型 内部 Arc<RwLock ,即,

    pub struct Obj {
        lock: Arc<RwLock<ObjData>>,
    }
    
    // internal helper, not public
    struct ObjData {
        // whatever fields Obj would have had go here
    }
    

    然后,您可以直接在 Obj ,并且调用方永远不需要显式处理锁,但您的方法可以完全根据需要处理它。这是从中受益的问题域(如UI对象)中相当常见的模式。

    如果有什么原因 Obj公司 确实需要有锁或没有锁都可用,然后定义一个特征。