use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::Arc;
macro_rules! instance_counter_cls {
($name:ident, $instances_name:ident) => {
static $instances_name: AtomicUsize = AtomicUsize::new(0);
pub struct $name {
instance: usize,
}
impl $name {
pub fn new() -> Self {
Self {
instance: $instances_name.fetch_add(1, Ordering::SeqCst),
}
}
pub fn instance(&self) -> usize {
self.instance
}
pub fn instances() -> usize {
$instances_name.load(Ordering::SeqCst)
}
}
};
}
instance_counter_cls!(InstanceCounterDep, INSTANCES_DEP);
instance_counter_cls!(InstanceCounter1, INSTANCES_1);
instance_counter_cls!(InstanceCounter2, INSTANCES_2);
#[derive(Default)]
pub struct TestProvider;
#[chassis::module]
impl TestProvider {
#[chassis(singleton)]
pub fn provide_singleton() -> Arc<InstanceCounterDep> {
Arc::new(InstanceCounterDep::new())
}
#[chassis(singleton)]
pub fn provide_singleton2() -> Arc<InstanceCounter2> {
Arc::new(InstanceCounter2::new())
}
#[chassis(singleton)]
pub fn provide_singleton1(_dep: Arc<InstanceCounter2>) -> Arc<InstanceCounter1> {
Arc::new(InstanceCounter1::new())
}
}
#[chassis::injector(modules = [TestProvider])]
pub trait TestFactory {
fn provide_singleton(&self) -> Arc<InstanceCounterDep>;
fn provide_singleton1(&self) -> Arc<InstanceCounter1>;
fn provide_singleton2(&self) -> Arc<InstanceCounter2>;
}
#[test]
fn check_dep() {
let injector = <dyn TestFactory>::new().unwrap();
injector.provide_singleton();
injector.provide_singleton();
let singleton = injector.provide_singleton();
assert_eq!(0, singleton.instance());
assert_eq!(1, InstanceCounterDep::instances());
}
#[test]
fn check_multiple() {
let injector = <dyn TestFactory>::new().unwrap();
injector.provide_singleton1();
injector.provide_singleton2();
let singleton = injector.provide_singleton2();
assert_eq!(0, singleton.instance());
assert_eq!(1, InstanceCounter1::instances());
assert_eq!(1, InstanceCounter2::instances());
}