如何在rust中实现id锁?

  • 本文关键字:id 实现 rust rust mutex
  • 更新时间 :
  • 英文 :


我必须锁定由id标识的不同进程。

所以我写代码如下:

use std::collections::HashMap;
use std::ptr::null;
use std::sync::{Arc, Mutex, MutexGuard};
pub struct IDMutex {
m: Mutex<HashMap<String, Arc<Mutex<u8>>>>,
}
pub struct IDMutexGuard<'a> {
mutex: &'a IDMutex,
local_mutex: Arc<Mutex<u8>>,
local_guard: *const MutexGuard<'a, u8>,
id: String,
}
impl<'a> IDMutexGuard<'a> {
fn new(mutex: &'a IDMutex, id: String) -> Self {
let mut guard: MutexGuard<'_, _> = mutex.m.lock().unwrap();
let local_mutex = guard.entry(id.clone()).or_default().clone();
let mut res = Self {
mutex,
id,
local_mutex: local_mutex,
local_guard: null(),
};
res.local_guard = &res.local_mutex.lock().unwrap();
res
}
}
impl<'a> Drop for IDMutexGuard<'a> {
fn drop(&mut self) {
drop(&mut self.local_guard);
let mut guard = self.mutex.m.lock().unwrap();
guard.remove(&self.id);
}
}
impl IDMutex {
fn lock(&self, id: String) -> IDMutexGuard<'_> {
IDMutexGuard::new(&self, id)
}
}

它的实现类似于标准库的互斥锁和MutexGuard,但有一个id参数,以便我可以锁定一些id。但由于借来的规则,它无法构建。

那么有什么办法可以解决这些问题吗?

我知道正确的方法是选择共享状态,然后使用标准库的互斥锁来锁定它们。但由于一些历史原因,这确实是一种具有挑战性的方式,我希望将来我能这样做。

那么有什么办法可以解决这些问题吗?

不要在现有的基础上创建自己的MutexGuard。这实际上是不可行的,因为您需要同时返回所拥有的互斥锁和MutexGuard,因为后者借用了前者。此外,拥有的互斥锁实际上是从Arc中借用的,所以您也需要返回那个。但是返回Arc的行为移动了它,这是不允许的,因为这样引用可能无效。

也不要使用低级代码创建自己的MutexGuard,这是可能的,但并不容易。

我看到了两种摆脱困境的方法:

  1. 使用一个基于回调的系统,让你的API管理锁,调用者提供一个fn,一旦你调用了这个信息,这是相当有限的,但它对调用者和被调用者都很简单。

  2. 返回从映射克隆的Arc,并让调用者处理锁定它。这一点非常重要,因为根据您的设置设计方式,通常会锁定地图,获取物品,然后在您仍然持有物品时解锁地图,这意味着调用者可能想要try_lock第二个锁。

最新更新