use std::sync::Arc;
use std::sync::atomic::{AtomicI64, Ordering};
use crate::basic_locker::BasicLocker;
use crate::handle_locker::HandleLocker;
use crate::lock_manager::LockManager;
use crate::locker::Locker;
use crate::thread_locker::ThreadLocker;
pub struct LockerFactory {
next_id: AtomicI64,
lock_manager: Arc<LockManager>,
default_timeout_ms: u64,
}
impl LockerFactory {
pub fn new(lock_manager: Arc<LockManager>) -> Self {
LockerFactory {
next_id: AtomicI64::new(1),
lock_manager,
default_timeout_ms: 5000, }
}
pub fn with_timeout(
lock_manager: Arc<LockManager>,
timeout_ms: u64,
) -> Self {
LockerFactory {
next_id: AtomicI64::new(1),
lock_manager,
default_timeout_ms: timeout_ms,
}
}
pub fn next_id(&self) -> i64 {
self.next_id.fetch_add(1, Ordering::Relaxed)
}
pub fn create_basic_locker(&self) -> BasicLocker {
BasicLocker::with_timeout(
self.next_id(),
self.lock_manager.clone(),
self.default_timeout_ms,
)
}
pub fn create_basic_locker_with_timeout(
&self,
timeout_ms: u64,
) -> BasicLocker {
BasicLocker::with_timeout(
self.next_id(),
self.lock_manager.clone(),
timeout_ms,
)
}
pub fn create_basic_locker_no_wait(&self) -> BasicLocker {
BasicLocker::with_no_wait(self.next_id(), self.lock_manager.clone())
}
pub fn create_thread_locker(&self) -> ThreadLocker {
ThreadLocker::with_timeout(
self.next_id(),
self.lock_manager.clone(),
self.default_timeout_ms,
)
}
pub fn create_thread_locker_with_timeout(
&self,
timeout_ms: u64,
) -> ThreadLocker {
ThreadLocker::with_timeout(
self.next_id(),
self.lock_manager.clone(),
timeout_ms,
)
}
pub fn create_handle_locker(&self) -> HandleLocker {
HandleLocker::with_timeout(
self.next_id(),
self.lock_manager.clone(),
self.default_timeout_ms,
)
}
pub fn create_handle_locker_with_timeout(
&self,
timeout_ms: u64,
) -> HandleLocker {
HandleLocker::with_timeout(
self.next_id(),
self.lock_manager.clone(),
timeout_ms,
)
}
pub fn create_handle_locker_with_buddy(
&self,
buddy: &dyn Locker,
) -> HandleLocker {
HandleLocker::with_buddy(
self.next_id(),
self.lock_manager.clone(),
buddy,
)
}
pub fn default_timeout_ms(&self) -> u64 {
self.default_timeout_ms
}
pub fn set_default_timeout(&mut self, timeout_ms: u64) {
self.default_timeout_ms = timeout_ms;
}
pub fn lock_manager(&self) -> &Arc<LockManager> {
&self.lock_manager
}
}
#[cfg(test)]
mod tests {
use super::*;
fn setup() -> LockerFactory {
let lm = Arc::new(LockManager::new());
LockerFactory::new(lm)
}
#[test]
fn test_id_generation() {
let factory = setup();
let id1 = factory.next_id();
let id2 = factory.next_id();
let id3 = factory.next_id();
assert_eq!(id1, 1);
assert_eq!(id2, 2);
assert_eq!(id3, 3);
}
#[test]
fn test_id_generation_is_sequential() {
let factory = setup();
let ids: Vec<i64> = (0..10).map(|_| factory.next_id()).collect();
for (i, &id) in ids.iter().enumerate() {
assert_eq!(id, (i + 1) as i64);
}
}
#[test]
fn test_create_basic_locker() {
let factory = setup();
let locker = factory.create_basic_locker();
assert_eq!(locker.id(), 1);
assert!(!locker.is_transactional());
assert!(locker.is_open());
}
#[test]
fn test_create_thread_locker() {
let factory = setup();
let locker = factory.create_thread_locker();
assert_eq!(locker.id(), 1);
assert!(!locker.is_transactional());
assert!(locker.is_open());
assert!(locker.get_thread_id() > 0);
}
#[test]
fn test_create_handle_locker() {
let factory = setup();
let locker = factory.create_handle_locker();
assert_eq!(locker.id(), 1);
assert!(!locker.is_transactional());
assert!(locker.is_open());
}
#[test]
fn test_unique_ids_across_types() {
let factory = setup();
let basic = factory.create_basic_locker();
let thread = factory.create_thread_locker();
let handle = factory.create_handle_locker();
assert_eq!(basic.id(), 1);
assert_eq!(thread.id(), 2);
assert_eq!(handle.id(), 3);
}
#[test]
fn test_with_timeout() {
let lm = Arc::new(LockManager::new());
let factory = LockerFactory::with_timeout(lm, 10000);
assert_eq!(factory.default_timeout_ms(), 10000);
let locker = factory.create_basic_locker();
assert_eq!(locker.lock_timeout_ms(), 10000);
}
#[test]
fn test_set_default_timeout() {
let mut factory = setup();
factory.set_default_timeout(15000);
assert_eq!(factory.default_timeout_ms(), 15000);
let locker = factory.create_basic_locker();
assert_eq!(locker.lock_timeout_ms(), 15000);
}
#[test]
fn test_create_with_custom_timeout() {
let factory = setup();
let locker = factory.create_basic_locker_with_timeout(20000);
assert_eq!(locker.lock_timeout_ms(), 20000);
}
#[test]
fn test_create_no_wait() {
let factory = setup();
let locker = factory.create_basic_locker_no_wait();
assert!(locker.default_no_wait());
}
}