init
This commit is contained in:
@@ -0,0 +1,81 @@
|
||||
use std::collections::HashMap;
|
||||
use std::hash::Hash;
|
||||
use std::sync::{Arc, Weak};
|
||||
use tokio::sync::{Mutex, OwnedMutexGuard, RwLock, RwLockReadGuard, RwLockWriteGuard};
|
||||
|
||||
/// Structure gérant les garde-fous pour un verrou scopé.
|
||||
pub struct ScopedGuard<'a, K: Eq + Hash + Clone> {
|
||||
_global_read_guard: RwLockReadGuard<'a, ()>,
|
||||
_local_guard: OwnedMutexGuard<()>,
|
||||
key: K,
|
||||
manager: &'a ScopedLockManager<K>,
|
||||
}
|
||||
|
||||
impl<'a, K: Eq + Hash + Clone> Drop for ScopedGuard<'a, K> {
|
||||
fn drop(&mut self) {
|
||||
// Optionnel : Nettoyage des Mutex orphelins dans la HashMap scopée
|
||||
let mut map = self.manager.scopes.blocking_lock();
|
||||
if let Some(weak) = map.get(&self.key) {
|
||||
if weak.strong_count() == 0 {
|
||||
map.remove(&self.key);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Default)]
|
||||
pub struct ScopedLockManager<K: Eq + Hash + Clone> {
|
||||
global_lock: Arc<RwLock<()>>,
|
||||
scopes: Arc<Mutex<HashMap<K, Weak<Mutex<()>>>>>,
|
||||
}
|
||||
|
||||
impl<K: Eq + Hash + Clone> ScopedLockManager<K> {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
global_lock: Arc::new(RwLock::new(())),
|
||||
scopes: Arc::new(Mutex::new(HashMap::new())),
|
||||
}
|
||||
}
|
||||
|
||||
/// Acquiert le verrou global (Exclusif / Write Lock).
|
||||
/// Bloque tous les autres verrous globaux et tous les verrous scopés.
|
||||
pub async fn lock_global(&self) -> RwLockWriteGuard<'_, ()> {
|
||||
self.global_lock.write().await
|
||||
}
|
||||
|
||||
/// Acquiert un verrou ciblé sur une clé `key` (ex: server_id ou user_id).
|
||||
/// Permet des exécutions parallèles sur des `key` différentes,
|
||||
/// mais garantit la sérialisation pour la même `key`.
|
||||
pub async fn lock_scope(&self, key: K) -> ScopedGuard<'_, K> {
|
||||
// 1. Prendre une garde de lecture (Read) sur le verrou global
|
||||
let global_read = self.global_lock.read().await;
|
||||
|
||||
// 2. Récupérer ou créer le Mutex dédié à la clé `key`
|
||||
let local_mutex = {
|
||||
let mut map = self.scopes.lock().await;
|
||||
if let Some(weak) = map.get(&key) {
|
||||
if let Some(arc) = weak.upgrade() {
|
||||
arc
|
||||
} else {
|
||||
let arc = Arc::new(Mutex::new(()));
|
||||
map.insert(key.clone(), Arc::downgrade(&arc));
|
||||
arc
|
||||
}
|
||||
} else {
|
||||
let arc = Arc::new(Mutex::new(()));
|
||||
map.insert(key.clone(), Arc::downgrade(&arc));
|
||||
arc
|
||||
}
|
||||
};
|
||||
|
||||
// 3. Verrouiller le Mutex local
|
||||
let local_guard = local_mutex.lock_owned().await;
|
||||
|
||||
ScopedGuard {
|
||||
_global_read_guard: global_read,
|
||||
_local_guard: local_guard,
|
||||
key,
|
||||
manager: self,
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user