use std::ops::{Deref, DerefMut};
use crate::runtime::Runtime;
#[derive(Debug)]
pub struct RuntimePool {
tx: async_channel::Sender<Runtime>,
rx: async_channel::Receiver<Runtime>,
}
impl RuntimePool {
pub fn new(runtimes: Vec<Runtime>) -> Self {
let (tx, rx) = async_channel::bounded(runtimes.len().max(1));
for rt in runtimes {
let _ = tx.try_send(rt);
}
Self { tx, rx }
}
pub fn size(&self) -> usize {
self.tx.capacity().unwrap_or(0)
}
pub async fn get(&self) -> RuntimeGuard {
let rt = self
.rx
.recv()
.await
.expect("runtime pool channel cannot be closed while the pool is alive");
RuntimeGuard {
rt: Some(rt),
tx: self.tx.clone(),
}
}
}
#[derive(Debug)]
pub struct RuntimeGuard {
rt: Option<Runtime>,
tx: async_channel::Sender<Runtime>,
}
impl Deref for RuntimeGuard {
type Target = Runtime;
fn deref(&self) -> &Self::Target {
self.rt.as_ref().expect("runtime present until drop")
}
}
impl DerefMut for RuntimeGuard {
fn deref_mut(&mut self) -> &mut Self::Target {
self.rt.as_mut().expect("runtime present until drop")
}
}
impl Drop for RuntimeGuard {
fn drop(&mut self) {
if let Some(rt) = self.rt.take() {
let _ = self.tx.try_send(rt);
}
}
}