use once_cell::sync::OnceCell;
use parking_lot::{Mutex, RwLock};
use std::sync::Arc;
use crate::CoreIdGenerator;
use crate::IdGeneratorOptions;
use crate::OptionError;
pub struct IdInstance;
impl IdInstance {
pub fn init(options: IdGeneratorOptions) -> Result<(), OptionError> {
IdInstance::get_instance().lock().init(options)
}
pub fn set_options(options: IdGeneratorOptions) -> Result<(), OptionError> {
IdInstance::get_instance().lock().set_options(options)
}
pub fn get_options() -> IdGeneratorOptions {
IdInstance::get_instance().lock().get_options()
}
pub fn next_id() -> i64 {
IdInstance::get_instance().lock().next_id()
}
fn get_instance() -> &'static Mutex<CoreIdGenerator> {
static INSTANCE: OnceCell<Mutex<CoreIdGenerator>> = OnceCell::new();
INSTANCE.get_or_init(|| Mutex::new(CoreIdGenerator::default()))
}
}
pub struct IdVecInstance;
impl IdVecInstance {
pub fn init(mut options: Vec<IdGeneratorOptions>) -> Result<(), OptionError> {
if options.is_empty() {
return Err(OptionError::InvalidVecLen(0));
}
let mut instances = IdVecInstance::get_instance().write();
instances.clear();
for option in options.drain(..) {
let mut instance = CoreIdGenerator::default();
instance.init(option)?;
instances.push(Arc::new(Mutex::new(instance)));
}
Ok(())
}
pub fn set_options(index: usize, options: IdGeneratorOptions) -> Result<(), OptionError> {
let reader = {
let r = IdVecInstance::get_instance().read();
if index >= r.len() {
return Err(OptionError::IndexOutOfRange(index));
}
Arc::clone(&r[index])
};
reader.lock().set_options(options)?;
Ok(())
}
pub fn get_options(index: usize) -> Result<IdGeneratorOptions, OptionError> {
let reader = {
let r = IdVecInstance::get_instance().read();
if index >= r.len() {
return Err(OptionError::IndexOutOfRange(index));
}
Arc::clone(&r[index])
};
let options = reader.lock().get_options();
Ok(options)
}
pub fn next_id(index: usize) -> i64 {
let reader = {
let r = IdVecInstance::get_instance().read();
Arc::clone(&r[index])
};
let id = reader.lock().next_id();
id
}
fn get_instance() -> &'static RwLock<Vec<Arc<Mutex<CoreIdGenerator>>>> {
static INSTANCE: OnceCell<RwLock<Vec<Arc<Mutex<CoreIdGenerator>>>>> = OnceCell::new();
INSTANCE.get_or_init(|| RwLock::new(Vec::new()))
}
}