pub(super) use crate::score::energy_state::EnergyRow as ServiceEnergy;
pub(super) use crate::score::scaphandre::state::monotonic_ms;
crate::score::energy_state::impl_energy_state! {
#[derive(Debug, Default)]
pub struct AlumetState;
}
use std::sync::Arc;
use std::sync::atomic::{AtomicU64, Ordering};
#[derive(Debug, Default)]
pub struct DbEnergyState {
cumulative_kwh_bits: AtomicU64,
consumed_kwh_bits: AtomicU64,
last_update_ms: AtomicU64,
}
impl DbEnergyState {
#[must_use]
pub fn new() -> Arc<Self> {
Arc::new(Self::default())
}
pub(crate) fn mark_alive(&self, now_ms: u64) {
self.last_update_ms.store(now_ms, Ordering::SeqCst);
}
pub(crate) fn add_window_kwh(&self, kwh: f64, now_ms: u64) {
let _ = self
.cumulative_kwh_bits
.try_update(Ordering::SeqCst, Ordering::SeqCst, |bits| {
Some((f64::from_bits(bits) + kwh).to_bits())
});
self.last_update_ms.store(now_ms, Ordering::SeqCst);
}
pub fn take_window_kwh(&self, now_ms: u64, staleness_ms: u64) -> Option<f64> {
let last = self.last_update_ms.load(Ordering::SeqCst);
if now_ms.saturating_sub(last) > staleness_ms {
return None;
}
let cumulative_bits = self.cumulative_kwh_bits.load(Ordering::SeqCst);
let previous_bits = self
.consumed_kwh_bits
.swap(cumulative_bits, Ordering::SeqCst);
let delta = f64::from_bits(cumulative_bits) - f64::from_bits(previous_bits);
(delta > 0.0 && delta.is_finite()).then_some(delta)
}
}