subspace_farmer/plotter/gpu/
gpu_encoders_manager.rs

1//! Thread pool managing utilities for plotting purposes
2
3use crate::plotter::gpu::GpuRecordsEncoder;
4use event_listener::Event;
5use parking_lot::Mutex;
6use std::num::{NonZeroUsize, TryFromIntError};
7use std::ops::{Deref, DerefMut};
8use std::sync::Arc;
9
10/// Wrapper around [`GpuEncoder`] that on `Drop` will return thread pool back into
11/// corresponding [`GpuRecordsEncoderManager`].
12#[derive(Debug)]
13#[must_use]
14pub(super) struct GpuRecordsEncoderGuard<GRE> {
15    inner: Arc<(Mutex<Vec<GRE>>, Event)>,
16    gpu_records_encoder: Option<GRE>,
17}
18
19impl<GRE> Deref for GpuRecordsEncoderGuard<GRE> {
20    type Target = GRE;
21
22    #[inline]
23    fn deref(&self) -> &Self::Target {
24        self.gpu_records_encoder
25            .as_ref()
26            .expect("Value exists until `Drop`; qed")
27    }
28}
29
30impl<GRE> DerefMut for GpuRecordsEncoderGuard<GRE> {
31    #[inline]
32    fn deref_mut(&mut self) -> &mut Self::Target {
33        self.gpu_records_encoder
34            .as_mut()
35            .expect("Value exists until `Drop`; qed")
36    }
37}
38
39impl<GRE> Drop for GpuRecordsEncoderGuard<GRE> {
40    #[inline]
41    fn drop(&mut self) {
42        let (mutex, event) = &*self.inner;
43        mutex.lock().push(
44            self.gpu_records_encoder
45                .take()
46                .expect("Happens only once in `Drop`; qed"),
47        );
48        event.notify_additional(1);
49    }
50}
51
52/// GPU records encoder manager.
53///
54/// This abstraction wraps a set of GPU records encoders and allows to use them one at a time.
55#[derive(Debug)]
56pub(super) struct GpuRecordsEncoderManager<GRE> {
57    inner: Arc<(Mutex<Vec<GRE>>, Event)>,
58    gpu_records_encoders: NonZeroUsize,
59}
60
61impl<GRE> Clone for GpuRecordsEncoderManager<GRE> {
62    fn clone(&self) -> Self {
63        Self {
64            inner: Arc::clone(&self.inner),
65            gpu_records_encoders: self.gpu_records_encoders,
66        }
67    }
68}
69
70impl<GRE> GpuRecordsEncoderManager<GRE>
71where
72    GRE: GpuRecordsEncoder,
73{
74    /// Create new instance.
75    ///
76    /// Returns an error if empty list of encoders is provided.
77    pub(super) fn new(gpu_records_encoders: Vec<GRE>) -> Result<Self, TryFromIntError> {
78        let count = gpu_records_encoders.len().try_into()?;
79
80        Ok(Self {
81            inner: Arc::new((Mutex::new(gpu_records_encoders), Event::new())),
82            gpu_records_encoders: count,
83        })
84    }
85
86    /// How many gpu records encoders are being managed here
87    pub(super) fn gpu_records_encoders(&self) -> NonZeroUsize {
88        self.gpu_records_encoders
89    }
90
91    /// Get one of inner thread pool pairs, will wait until one is available if needed
92    pub(super) async fn get_encoder(&self) -> GpuRecordsEncoderGuard<GRE> {
93        let (mutex, event) = &*self.inner;
94
95        let gpu_records_encoder = loop {
96            let listener = event.listen();
97
98            if let Some(thread_pool_pair) = mutex.lock().pop() {
99                break thread_pool_pair;
100            }
101
102            listener.await;
103        };
104
105        GpuRecordsEncoderGuard {
106            inner: Arc::clone(&self.inner),
107            gpu_records_encoder: Some(gpu_records_encoder),
108        }
109    }
110}