use std::{
collections::HashMap,
sync::{RwLock, RwLockReadGuard, RwLockWriteGuard},
};
use rpki::ca::idexchange::MyHandle;
#[derive(Debug, Default)]
struct HandleLockMap(HashMap<MyHandle, RwLock<()>>);
impl HandleLockMap {
fn create_handle_lock(&mut self, handle: MyHandle) {
self.0.insert(handle, RwLock::new(()));
}
fn has_handle(&self, handle: &MyHandle) -> bool {
self.0.contains_key(handle)
}
fn drop_handle_lock(&mut self, handle: &MyHandle) {
self.0.remove(handle);
}
}
pub struct HandleLock<'a> {
map: RwLockReadGuard<'a, HandleLockMap>,
handle: MyHandle,
}
impl HandleLock<'_> {
pub fn read(&self) -> RwLockReadGuard<'_, ()> {
self.map.0.get(&self.handle).unwrap().read().unwrap()
}
pub fn write(&self) -> RwLockWriteGuard<'_, ()> {
self.map.0.get(&self.handle).unwrap().write().unwrap()
}
}
#[derive(Debug, Default)]
pub struct HandleLocks {
locks: RwLock<HandleLockMap>,
}
impl HandleLocks {
pub fn for_handle(&self, handle: MyHandle) -> HandleLock<'_> {
{
let map = self.locks.read().unwrap();
if map.has_handle(&handle) {
return HandleLock { map, handle };
}
}
{
let mut map = self.locks.write().unwrap();
if !map.has_handle(&handle) {
map.create_handle_lock(handle.clone());
}
}
self.for_handle(handle)
}
pub fn drop_handle(&self, handle: &MyHandle) {
let mut map = self.locks.write().unwrap();
map.drop_handle_lock(handle);
}
}