#![allow(dead_code)]
use crate::pool::pool::PoolInner;
use crate::pool::KeyedPoolFactory;
use std::sync::Weak;
use std::time::{Duration, Instant};
use tokio::sync::OwnedSemaphorePermit;
#[derive(Eq, PartialEq, Copy, Clone, Debug)]
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) id: u32,
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<Weak<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 {
id: self.id,
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 fn idle_duration(&self) -> Duration {
self.last_return.elapsed()
}
pub fn create_duration(&self) -> Duration {
self.create.elapsed()
}
pub fn expired(&self, max_lifetime: Duration, idle_timeout: Duration) -> bool {
self.create.elapsed() >= max_lifetime || self.last_return.elapsed() >= idle_timeout
}
pub(super) fn take(&mut self) -> Option<T> {
self.obj.take()
}
pub(super) fn snapshot(&mut self) -> Self {
Self {
id: self.id,
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: self.pool.take(),
_permit: self._permit.take(),
obj: self.obj.take(),
key: self.key.take(),
}
}
pub(super) fn restore(&mut self, mut that: Self) {
self.state = that.state;
self.pool = that.pool.take();
self._permit = that._permit.take();
self.obj = that.obj.take();
self.key = that.key.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 {
id: 0,
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::EvictionReturnToHead
| PooledObjectState::Invalid
| PooledObjectState::Abandoned
| PooledObjectState::Returning => return,
_ => {}
};
let Some(obj) = self.obj.take() else {
return;
};
let Some(key) = self.key.take() else {
return;
};
let Some(pool) = self.pool.take() else {
return;
};
self._permit = None;
self.state = PooledObjectState::Returning;
let new_pooled = self.drop_return_new();
tokio::spawn(async move {
let Some(pool) = pool.upgrade() else {
return;
};
pool.return_to_pool(new_pooled, key, obj).await;
});
}
}