use glam::Vec3;
use indicatrix_net::client::Accumulator;
use std::{
collections::VecDeque,
sync::{
Arc, Mutex, PoisonError,
atomic::{AtomicU32, Ordering},
},
};
pub(in crate::bridge::export_thread) struct RemoteProgress {
pub(super) accum: Mutex<Vec<Vec3>>,
pub(super) traced: AtomicU32,
pub(super) in_flight: Mutex<Option<Arc<Mutex<Accumulator>>>>,
pub(super) notes: Mutex<VecDeque<String>>,
}
impl RemoteProgress {
pub(in crate::bridge::export_thread) fn new(pixel_count: usize) -> Self {
Self {
accum: Mutex::new(vec![Vec3::ZERO; pixel_count]),
traced: AtomicU32::new(0),
in_flight: Mutex::new(None),
notes: Mutex::new(VecDeque::new()),
}
}
pub(in crate::bridge::export_thread) fn samples_done(&self) -> u32 {
let in_flight = self
.in_flight
.lock()
.unwrap_or_else(PoisonError::into_inner);
let live = in_flight.as_ref().map_or(0, |acc| {
acc.lock()
.unwrap_or_else(PoisonError::into_inner)
.samples_done()
});
drop(in_flight);
self.traced.load(Ordering::Relaxed) + live
}
pub(in crate::bridge::export_thread) fn preview_buffer(&self) -> Vec<Vec3> {
let mut buf = self
.accum
.lock()
.unwrap_or_else(PoisonError::into_inner)
.clone();
let in_flight = self
.in_flight
.lock()
.unwrap_or_else(PoisonError::into_inner);
if let Some(acc) = in_flight.as_ref() {
let acc = acc.lock().unwrap_or_else(PoisonError::into_inner);
for (dst, src) in buf.iter_mut().zip(acc.buffer()) {
*dst += *src;
}
}
drop(in_flight);
buf
}
pub(in crate::bridge::export_thread) fn take_note(&self) -> Option<String> {
self.notes
.lock()
.unwrap_or_else(PoisonError::into_inner)
.pop_front()
}
pub(in crate::bridge::export_thread) fn into_buffer(self) -> Vec<Vec3> {
self.accum
.into_inner()
.unwrap_or_else(PoisonError::into_inner)
}
}