use std::collections::HashMap;
use std::ops::Deref;
use std::rc::Rc;
use std::sync::atomic::AtomicBool;
use std::sync::Arc;
use parking_lot::RwLock;
use crate::core::sync_mode::{FullSync, LocalSync};
use crate::param::{AccountGroupId, AccountId};
use super::internals::Slot;
use super::lock::{LocalTtlGate, MarketDataLock, NoopLock, ServiceTtlGate};
use super::quote::QuoteTtl;
use super::service::{InstrumentRegistry, MarketDataService};
use super::ttl::TtlSetting;
pub mod sealed {
pub trait Sealed {}
}
pub trait MarketDataSync: sealed::Sealed + Clone + 'static {
type Shared<T: 'static>: Clone + Deref<Target = T>;
type Lock<T>: MarketDataLock<T>;
type Gate: ServiceTtlGate;
fn new_shared<T: 'static>(&self, inner: T) -> Self::Shared<T>;
fn new_lock<T>(&self, inner: T) -> Self::Lock<T>;
fn new_gate(&self) -> Self::Gate {
Self::Gate::new_unset()
}
}
impl sealed::Sealed for LocalSync {}
impl sealed::Sealed for FullSync {}
impl MarketDataSync for LocalSync {
type Shared<T: 'static> = Rc<T>;
type Lock<T> = NoopLock<T>;
type Gate = LocalTtlGate;
#[inline]
fn new_shared<T: 'static>(&self, inner: T) -> Rc<T> {
Rc::new(inner)
}
#[inline]
fn new_lock<T>(&self, inner: T) -> NoopLock<T> {
NoopLock::new(inner)
}
}
impl MarketDataSync for FullSync {
type Shared<T: 'static> = Arc<T>;
type Lock<T> = RwLock<T>;
type Gate = AtomicBool;
#[inline]
fn new_shared<T: 'static>(&self, inner: T) -> Arc<T> {
Arc::new(inner)
}
#[inline]
fn new_lock<T>(&self, inner: T) -> RwLock<T> {
RwLock::new(inner)
}
}
pub struct MarketDataBuilder<Sync: MarketDataSync> {
default_ttl: QuoteTtl,
sync: Sync,
}
impl<Sync: MarketDataSync + Default> MarketDataBuilder<Sync> {
pub fn new(default_ttl: QuoteTtl) -> Self {
Self::with_sync(Sync::default(), default_ttl)
}
}
impl<Sync: MarketDataSync> MarketDataBuilder<Sync> {
pub fn with_sync(sync: Sync, default_ttl: QuoteTtl) -> Self {
Self { default_ttl, sync }
}
pub fn build(self) -> Sync::Shared<MarketDataService<Sync>> {
let account_ttl: Sync::Lock<HashMap<AccountId, TtlSetting>> =
self.sync.new_lock(HashMap::new());
let group_ttl: Sync::Lock<HashMap<AccountGroupId, TtlSetting>> =
self.sync.new_lock(HashMap::new());
let registry = self.sync.new_lock(InstrumentRegistry::new());
let slots: Sync::Lock<Vec<Slot<Sync>>> = self.sync.new_lock(Vec::new());
let has_service_level_ttl = self.sync.new_gate();
let service = MarketDataService {
default_ttl: self.default_ttl.as_duration(),
account_ttl,
group_ttl,
registry,
slots,
sync: self.sync.clone(),
has_service_level_ttl,
};
self.sync.new_shared(service)
}
}
impl MarketDataBuilder<LocalSync> {
pub fn full_sync(self) -> MarketDataBuilder<FullSync> {
MarketDataBuilder {
default_ttl: self.default_ttl,
sync: FullSync,
}
}
}