use std::{
sync::{Arc, Mutex},
time::{Duration, Instant},
};
#[derive(Debug, Default)]
pub struct SyncedTimer(Synced<Duration>);
impl SyncedTimer {
pub fn update_with_func<F, T>(&self, func: F) -> T
where
F: FnOnce() -> T,
{
let start = Instant::now();
let result = func(); let elapsed = start.elapsed();
self.0.with_lock(|t| *t += elapsed).unwrap();
result
}
pub fn get(&self) -> Duration {
self.0.with_lock(|t| *t).unwrap()
}
}
#[derive(Debug)]
pub struct Synced<T> {
internal: Arc<Mutex<T>>,
}
impl<T> Synced<T> {
pub fn with_lock<F, R>(
&self,
func: F,
) -> Result<R, std::sync::PoisonError<std::sync::MutexGuard<'_, T>>>
where
F: FnOnce(&mut T) -> R,
{
let mut guard = self.internal.lock()?;
Ok(func(&mut guard))
}
pub fn try_finalize(self) -> Option<T> {
Arc::into_inner(self.internal)?.into_inner().ok()
}
}
impl<T: Default> Default for Synced<T> {
fn default() -> Self {
Synced {
internal: Arc::new(Mutex::new(T::default())),
}
}
}
impl<T> From<T> for Synced<T> {
fn from(value: T) -> Self {
Synced {
internal: Arc::new(Mutex::new(value)),
}
}
}
impl<T> Clone for Synced<T> {
fn clone(&self) -> Self {
Synced {
internal: Arc::clone(&self.internal),
}
}
}
#[cfg(test)]
mod tests {
use crate::vec::arg_max;
use super::*;
fn scale_to_u64(vec: &[f32], upper_bound: f32) -> Vec<u64> {
vec.iter()
.map(|&x| {
let t = (upper_bound * x) as u64;
t.min(upper_bound as u64)
})
.collect()
}
#[test]
fn test_synced_with_lock_and_finalize() {
let synced = Synced::from(10);
let res = synced.with_lock(|v| {
*v += 5;
*v
});
assert_eq!(res.unwrap(), 15);
let finalized = synced.try_finalize();
assert_eq!(finalized, Some(15));
}
#[test]
fn test_synced_default() {
let synced: Synced<i32> = Synced::default();
let val = synced.try_finalize().unwrap();
assert_eq!(val, 0);
}
#[test]
fn test_synced_clone() {
let synced = Synced::from(42);
{
let cloned = synced.clone();
let _ = cloned.with_lock(|v| *v += 1);
}
let orig = synced.try_finalize().unwrap();
assert_eq!(orig, 43);
}
#[test]
fn test_arg_max() {
let v = vec![1, 3, 2, 5, 4];
let idx = arg_max(&v);
assert_eq!(idx, Some(3));
let empty: Vec<i32> = vec![];
assert_eq!(arg_max(&empty), None);
}
#[test]
fn test_scale_to_u64() {
let v = vec![0.0, 0.5, 1.0, 1.5];
let scaled = scale_to_u64(&v, 10.0);
assert_eq!(scaled, vec![0, 5, 10, 10]);
}
}