#![allow(dead_code)]
use crate::pool::pool::PoolInner;
use crate::pool::KeyedPoolFactory;
use std::sync::Arc;
use std::time::Instant;
use tokio::sync::OwnedSemaphorePermit;
#[derive(Eq, PartialEq, Copy, Clone)]
pub enum PooledObjectState {
Idle,
Allocated,
Eviction,
EvictionReturnToHead,
Validation,
ValidationPreallocated,
ValidationReturnToHead,
Invalid,
Abandoned,
Returning,
}
pub struct PooledObject<K, T, F>
where
K: Eq + std::hash::Hash + Clone + Send + Sync + 'static,
T: Send + Sync + 'static,
F: KeyedPoolFactory<K, T>,
{
pub(super) obj: Option<T>, pub(super) key: Option<K>,
pub(crate) state: PooledObjectState,
pub(super) create: Instant,
pub(super) last_borrow: Instant,
pub(super) last_use: Instant,
pub(super) last_return: Instant,
pub(super) borrowed_count: u64,
pub(super) pool: Option<Arc<PoolInner<K, T, F>>>,
pub(super) _permit: Option<OwnedSemaphorePermit>,
}
impl<K, T, F> PooledObject<K, T, F>
where
K: Eq + std::hash::Hash + Clone + Send + Sync + 'static,
T: Send + Sync + 'static,
F: KeyedPoolFactory<K, T>,
{
pub fn in_use(&mut self) {
self.last_use = Instant::now();
}
pub(super) fn drop_return_new(&self) -> Self {
PooledObject {
state: self.state,
create: self.create,
last_borrow: self.last_borrow,
last_use: self.last_use,
last_return: self.last_return,
borrowed_count: self.borrowed_count,
pool: None,
_permit: None,
obj: None,
key: None,
}
}
pub(super) fn take(&mut self) -> Option<T> {
self.obj.take()
}
}
impl<K, T, F> Default for PooledObject<K, T, F>
where
K: Eq + std::hash::Hash + Clone + Send + Sync + 'static,
T: Send + Sync + 'static,
F: KeyedPoolFactory<K, T>,
{
fn default() -> Self {
Self {
obj: None,
key: None,
state: PooledObjectState::Idle,
create: Instant::now(),
last_borrow: Instant::now(),
last_use: Instant::now(),
last_return: Instant::now(),
borrowed_count: 0,
pool: None,
_permit: None,
}
}
}
impl<K, T, F> std::ops::Deref for PooledObject<K, T, F>
where
K: Eq + std::hash::Hash + Clone + Send + Sync + 'static,
T: Send + Sync + 'static,
F: KeyedPoolFactory<K, T>,
{
type Target = T;
fn deref(&self) -> &Self::Target {
self.obj.as_ref().unwrap()
}
}
impl<K, T, F> std::ops::DerefMut for PooledObject<K, T, F>
where
K: Eq + std::hash::Hash + Clone + Send + Sync + 'static,
T: Send + Sync + 'static,
F: KeyedPoolFactory<K, T>,
{
fn deref_mut(&mut self) -> &mut Self::Target {
self.obj.as_mut().unwrap()
}
}
impl<K, T, F> Drop for PooledObject<K, T, F>
where
K: Eq + std::hash::Hash + Clone + Send + Sync + 'static,
T: Send + Sync + 'static,
F: KeyedPoolFactory<K, T>,
{
fn drop(&mut self) {
match self.state {
PooledObjectState::Eviction
| PooledObjectState::Invalid
| PooledObjectState::Abandoned
| PooledObjectState::Returning => return,
_ => {}
};
if let Some(mut obj) = self.obj.take() {
let Some(key) = self.key.clone() else {
return;
};
let Some(pool) = self.pool.clone() else {
return;
};
self._permit = None;
self.state = PooledObjectState::Returning;
self.last_return = Instant::now();
let new_pooed = self.drop_return_new();
tokio::spawn(async move {
let mut new_pooed = new_pooed;
let pools_read = pool.pools.read().await;
let Some(queue_arc) = pools_read.get(&key) else {
return;
};
if pool.config.test_on_return
&& !pool
.validate_pooled(&key, &mut new_pooed, Some(&mut obj))
.await
.unwrap_or(false)
{
return;
}
new_pooed.key = Some(key);
new_pooed.pool = Some(pool.clone());
new_pooed.obj = Some(obj);
let mut queue = queue_arc.lock().await;
new_pooed.state = PooledObjectState::Idle;
queue.push_back(new_pooed);
});
}
}
}