cortex_runtime/pool/
manager.rs1use crate::renderer::{RenderContext, Renderer};
7use anyhow::Result;
8use std::sync::atomic::{AtomicUsize, Ordering};
9use std::sync::Arc;
10use tokio::sync::Semaphore;
11
12pub struct ContextHandle {
14 context: Option<Box<dyn RenderContext>>,
15 _permit: tokio::sync::OwnedSemaphorePermit,
16 active_count: Arc<AtomicUsize>,
17}
18
19impl ContextHandle {
20 pub fn context(&self) -> &dyn RenderContext {
22 self.context
23 .as_ref()
24 .expect("context already taken")
25 .as_ref()
26 }
27
28 pub fn context_mut(&mut self) -> &mut dyn RenderContext {
30 self.context
31 .as_mut()
32 .expect("context already taken")
33 .as_mut()
34 }
35
36 pub fn take(mut self) -> Box<dyn RenderContext> {
38 self.context.take().expect("context already taken")
39 }
40}
41
42impl Drop for ContextHandle {
43 fn drop(&mut self) {
44 self.active_count.fetch_sub(1, Ordering::SeqCst);
45 }
46}
47
48pub struct PoolManager {
50 renderer: Arc<dyn Renderer>,
51 semaphore: Arc<Semaphore>,
52 max_contexts: usize,
53 active_count: Arc<AtomicUsize>,
54}
55
56impl PoolManager {
57 pub fn new(renderer: Arc<dyn Renderer>, max_contexts: usize) -> Self {
59 Self {
60 renderer,
61 semaphore: Arc::new(Semaphore::new(max_contexts)),
62 max_contexts,
63 active_count: Arc::new(AtomicUsize::new(0)),
64 }
65 }
66
67 pub async fn acquire(&self) -> Result<ContextHandle> {
71 let permit = Arc::clone(&self.semaphore)
72 .acquire_owned()
73 .await
74 .map_err(|e| anyhow::anyhow!("semaphore closed: {}", e))?;
75
76 let context = self.renderer.new_context().await?;
77 self.active_count.fetch_add(1, Ordering::SeqCst);
78
79 Ok(ContextHandle {
80 context: Some(context),
81 _permit: permit,
82 active_count: Arc::clone(&self.active_count),
83 })
84 }
85
86 pub async fn release(&self, handle: ContextHandle) -> Result<()> {
88 let context = handle.take();
89 context.close().await
90 }
91
92 pub fn active(&self) -> usize {
94 self.active_count.load(Ordering::SeqCst)
95 }
96
97 pub fn max_contexts(&self) -> usize {
99 self.max_contexts
100 }
101
102 pub fn available(&self) -> usize {
104 self.semaphore.available_permits()
105 }
106}