2026-05-09 16:27:04 +08:00
|
|
|
//! When exporting resources for C interface, resource management and ownership are important things.
|
|
|
|
|
//! In this dynamic library, we hold all resources' ownership in Rust world,
|
|
|
|
|
//! and only expose a token for C code manipulation.
|
|
|
|
|
//!
|
|
|
|
|
//! We need to create a container for holding all resources and providing corresponding operations.
|
|
|
|
|
//! So we introduce [ObjectPool] in this module for this purpose.
|
|
|
|
|
use slotmap::{DefaultKey, Key, KeyData, SlotMap};
|
|
|
|
|
use thiserror::Error as TeError;
|
|
|
|
|
|
|
|
|
|
/// Error occurs when operating with [ObjectPool].
|
|
|
|
|
#[derive(Debug, TeError)]
|
|
|
|
|
pub enum Error {
|
|
|
|
|
#[error("given token is not presented in object pool")]
|
|
|
|
|
NoSuchToken,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// The token for fetching obejct in [ObjectPool].
|
|
|
|
|
pub type Token = u64;
|
|
|
|
|
|
|
|
|
|
/// A pool for managing objects with unique tokens.
|
|
|
|
|
///
|
|
|
|
|
/// It is highly suggested to use this pool with [std::sync::RwLock] guard.
|
|
|
|
|
pub struct ObjectPool<T> {
|
|
|
|
|
objs: SlotMap<DefaultKey, T>,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<T> ObjectPool<T> {
|
|
|
|
|
pub fn new() -> Self {
|
|
|
|
|
Self {
|
|
|
|
|
objs: SlotMap::new(),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn key_to_token(key: &DefaultKey) -> Token {
|
|
|
|
|
key.data().as_ffi()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn token_to_key(token: Token) -> DefaultKey {
|
|
|
|
|
DefaultKey::from(KeyData::from_ffi(token))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn allocate(&mut self, value: T) -> Result<Token, Error> {
|
|
|
|
|
let key = self.objs.insert(value);
|
|
|
|
|
Ok(Self::key_to_token(&key))
|
|
|
|
|
}
|
|
|
|
|
|
2026-05-10 23:16:56 +08:00
|
|
|
pub fn free(&mut self, token: Token) -> Result<(), Error> {
|
|
|
|
|
let _ = self.pop(token)?;
|
|
|
|
|
Ok(())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn pop(&mut self, token: Token) -> Result<T, Error> {
|
2026-05-09 16:27:04 +08:00
|
|
|
match self.objs.remove(Self::token_to_key(token)) {
|
2026-05-10 23:16:56 +08:00
|
|
|
Some(obj) => Ok(obj),
|
2026-05-09 16:27:04 +08:00
|
|
|
None => Err(Error::NoSuchToken),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn get(&self, token: Token) -> Result<&T, Error> {
|
|
|
|
|
self.objs
|
|
|
|
|
.get(Self::token_to_key(token))
|
|
|
|
|
.ok_or(Error::NoSuchToken)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn get_mut(&mut self, token: Token) -> Result<&mut T, Error> {
|
|
|
|
|
self.objs
|
|
|
|
|
.get_mut(Self::token_to_key(token))
|
|
|
|
|
.ok_or(Error::NoSuchToken)
|
|
|
|
|
}
|
|
|
|
|
}
|