use super::counter_cell::{CounterCell, OptionalCounterCell};
use super::hardware_accumulator::HwMeasurementAcc;
use super::hardware_counter::HardwareCounterCell;
#[derive(Copy, Clone)]
pub struct ConditionedCounter<'a> {
parent: Option<&'a HardwareCounterCell>,
}
impl<'a> ConditionedCounter<'a> {
pub fn new(condition: bool, parent: &'a HardwareCounterCell) -> Self {
if condition {
Self::always(parent)
} else {
Self::never()
}
}
pub fn never() -> Self {
Self { parent: None }
}
pub fn always(parent: &'a HardwareCounterCell) -> Self {
Self {
parent: Some(parent),
}
}
#[inline]
fn make_optional_counter<C>(&self, c: C) -> OptionalCounterCell<'_>
where
C: Fn(&HardwareCounterCell) -> &CounterCell,
{
OptionalCounterCell::new(self.parent.map(c))
}
#[inline]
pub fn cpu_counter(&self) -> OptionalCounterCell<'_> {
self.make_optional_counter(|i| i.cpu_counter())
}
#[inline]
pub fn payload_io_read_counter(&self) -> OptionalCounterCell<'_> {
self.make_optional_counter(|i| i.payload_io_read_counter())
}
#[inline]
pub fn payload_index_io_read_counter(&self) -> OptionalCounterCell<'_> {
self.make_optional_counter(|i| i.payload_index_io_read_counter())
}
#[inline]
pub fn payload_index_io_write_counter(&self) -> OptionalCounterCell<'_> {
self.make_optional_counter(|i| i.payload_index_io_write_counter())
}
#[inline]
pub fn payload_io_write_counter(&self) -> OptionalCounterCell<'_> {
self.make_optional_counter(|i| i.payload_io_write_counter())
}
#[inline]
pub fn vector_io_read(&self) -> OptionalCounterCell<'_> {
self.make_optional_counter(|i| i.vector_io_read())
}
#[inline]
pub fn vector_io_write_counter(&self) -> OptionalCounterCell<'_> {
self.make_optional_counter(|i| i.vector_io_write_counter())
}
#[inline]
pub fn new_accumulator(&self) -> HwMeasurementAcc {
match self.parent {
Some(p) => p.new_accumulator(),
None => HwMeasurementAcc::disposable(),
}
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test_conditioned_counter_empty() {
let parent = HardwareCounterCell::new();
{
let condition = false;
let cc = ConditionedCounter::new(condition, &parent);
cc.cpu_counter().incr_delta(5);
}
assert_eq!(parent.cpu_counter().get(), 0);
assert_eq!(parent.accumulator.as_ref().unwrap().get_cpu(), 0);
}
#[test]
fn test_conditioned_counter_enabled() {
let parent = HardwareCounterCell::new();
{
let cc = ConditionedCounter::always(&parent);
cc.cpu_counter().incr_delta(5);
}
assert_eq!(parent.cpu_counter().get(), 5);
let parent_acc = parent.new_accumulator();
drop(parent); assert_eq!(parent_acc.get_cpu(), 5);
}
#[test]
fn test_conditioned_counter_enabled_into_hw_acc() {
let parent = HardwareCounterCell::new();
{
let cc = ConditionedCounter::always(&parent);
cc.new_accumulator() .get_counter_cell() .cpu_counter()
.incr_delta(5);
}
assert_eq!(parent.cpu_counter().get(), 0); assert_eq!(parent.accumulator.as_ref().unwrap().get_cpu(), 5);
}
#[test]
fn test_conditioned_counter_enabled_parent_hw_acc() {
let parent = HwMeasurementAcc::new();
{
let cell = parent.get_counter_cell();
let cc = ConditionedCounter::always(&cell);
cc.new_accumulator() .get_counter_cell() .cpu_counter()
.incr_delta(5);
}
assert_eq!(parent.get_cpu(), 5);
}
}