use crate::numeric_registry::NumericRegistry;
pub static VALUE_MONITOR_REGISTRY: NumericRegistry = NumericRegistry::new();
pub static CODE_MONITOR_REGISTRY: NumericRegistry = NumericRegistry::new();
#[macro_export]
macro_rules! get_static_id_by_registry {
($registry:expr) => {{
use rustmeter_beacon::_private::portable_atomic::{AtomicUsize, Ordering};
static LOCAL_MONITOR_VALUE_ID: AtomicUsize = AtomicUsize::new(0);
match LOCAL_MONITOR_VALUE_ID.load(Ordering::Relaxed) {
0 => {
let id = VALUE_MONITOR_REGISTRY.allocate_new_id();
let res = LOCAL_MONITOR_VALUE_ID.compare_exchange(
0,
id,
Ordering::Relaxed,
Ordering::Relaxed,
);
match res {
Ok(_) => {
(id, true)
}
Err(actual) => {
(actual, false)
}
}
}
id => (id, false),
}
}};
}
#[allow(unused_variables)]
pub fn defmt_trace_new_monitored_value(name: &str, local_id: usize) {
#[cfg(feature = "defmt")]
defmt::trace!(
"Registered new monitored value: {} with id {}",
name,
local_id
);
}
#[macro_export]
macro_rules! monitor_value {
($name:literal, $val:expr) => {
const _: () = {
core::assert!($name.len() <= 20, "Name of value to be monitored must be 20 characters or less");
};
use crate::monitors::{CODE_MONITOR_REGISTRY, VALUE_MONITOR_REGISTRY};
use rustmeter_beacon::protocol::MonitorValuePayload;
let (local_id, registered_newly) = get_static_id_by_registry!(VALUE_MONITOR_REGISTRY);
if registered_newly {
let payload = rustmeter_beacon::protocol::TypeDefinitionPayload::ValueMonitor {
value_id: local_id as u8,
name: $name,
};
rustmeter_beacon::tracing::write_tracing_event(rustmeter_beacon::protocol::EventPayload::TypeDefinition(payload));
rustmeter_beacon::monitors::defmt_trace_new_monitored_value($name, local_id);
}
rustmeter_beacon::tracing::write_tracing_event(rustmeter_beacon::protocol::EventPayload::MonitorValue {
value_id: local_id as u8,
value: $val.into(),
});
};
}
pub struct DropGuard<F: FnOnce()> {
drop_fn: Option<F>,
}
impl<F: FnOnce()> DropGuard<F> {
pub fn new(drop_fn: F) -> Self {
Self {
drop_fn: Some(drop_fn),
}
}
}
impl<F: FnOnce()> Drop for DropGuard<F> {
fn drop(&mut self) {
if let Some(f) = self.drop_fn.take() {
f();
}
}
}
#[allow(unused_variables)]
pub fn defmt_trace_new_scope(name: &str, local_id: usize) {
#[cfg(feature = "defmt")]
defmt::trace!(
"Registered new scope monitor: {} with id {}",
name,
local_id
);
}
#[macro_export]
macro_rules! monitor_scoped {
($name:literal, $body:block) => {{
const _: () = {
core::assert!($name.len() <= 20, "Scope name must be 20 characters or less");
};
use rustmeter_beacon::monitors::{CODE_MONITOR_REGISTRY, VALUE_MONITOR_REGISTRY};
use rustmeter_beacon::get_static_id_by_registry;
use rustmeter_beacon::tracing::write_tracing_event;
let (local_id, registered_newly) = get_static_id_by_registry!(CODE_MONITOR_REGISTRY);
if registered_newly {
let payload = rustmeter_beacon::protocol::TypeDefinitionPayload::ScopeMonitor {
monitor_id: local_id as u8,
name: $name,
};
write_tracing_event(rustmeter_beacon::protocol::EventPayload::TypeDefinition(payload));
rustmeter_beacon::monitors::defmt_trace_new_scope($name, local_id);
}
let _guard = rustmeter_beacon::monitors::DropGuard::new(|| {
rustmeter_beacon::protocol::raw_writers::write_monitor_end();
});
rustmeter_beacon::protocol::raw_writers::write_monitor_start(local_id as u8);
{ $body }
}};
}
#[allow(unused_variables)]
pub fn defmt_trace_new_function_monitor(name: &str, local_id: usize) {
#[cfg(feature = "defmt")]
defmt::trace!(
"Registered new function monitor: {} with id {}",
name,
local_id
);
}