#[cfg(test)]
mod tests;
mod controller;
mod draw;
mod worker;
use massa_hash::Hash;
use massa_models::{address::Address, slot::Slot};
use massa_pos_exports::{PosResult, Selection};
use parking_lot::{Condvar, Mutex, RwLock, RwLockReadGuard};
use std::{
collections::{BTreeMap, HashMap, VecDeque},
sync::Arc,
};
pub(crate) enum Command {
DrawInput {
cycle: u64,
lookback_rolls: BTreeMap<Address, u64>,
lookback_seed: Hash,
},
Stop,
}
#[derive(Debug)]
pub(crate) struct DrawCache(pub VecDeque<CycleDraws>);
impl DrawCache {
pub fn get_available_cycles_range(&self) -> Option<std::ops::RangeInclusive<u64>> {
match self.0.front() {
None => None,
Some(cd) => {
let upper_bound = cd
.cycle
.checked_add(self.0.len().try_into().expect("overflow on cycles length"))
.expect("overflow on cycle delta");
Some(cd.cycle..=upper_bound)
}
}
}
pub fn get_cycle_index(&self, cycle: u64) -> Option<usize> {
let first_cycle = match self.0.front() {
Some(c) => c.cycle,
None => return None, };
if cycle < first_cycle {
return None; }
let index: usize = match (cycle - first_cycle).try_into() {
Ok(idx) => idx,
Err(_) => return None, };
if index >= self.0.len() {
return None; }
Some(index)
}
pub fn get(&self, cycle: u64) -> Option<&CycleDraws> {
self.get_cycle_index(cycle).and_then(|idx| self.0.get(idx))
}
}
#[derive(Debug)]
pub(crate) struct CycleDraws {
pub cycle: u64,
pub draws: HashMap<Slot, Selection>,
}
pub(crate) type DrawCachePtr = Arc<(RwLockCondvar, RwLock<PosResult<DrawCache>>)>;
pub use worker::start_selector_worker;
#[derive(Default)]
struct RwLockCondvar {
mutex: Mutex<()>,
condvar: Condvar,
}
impl RwLockCondvar {
fn wait<T>(&self, rwlock_read_guard: &mut RwLockReadGuard<T>) {
let mutex_guard = self.mutex.lock();
RwLockReadGuard::unlocked(rwlock_read_guard, || {
let mut mutex_guard = mutex_guard;
self.condvar.wait(&mut mutex_guard);
});
}
fn notify_all(&self) {
self.condvar.notify_all();
}
}