1
0

feat: add object pool for cdylib

This commit is contained in:
2026-05-09 16:27:04 +08:00
parent d4b52efee0
commit 6804b96078
5 changed files with 96 additions and 3 deletions

16
Cargo.lock generated
View File

@@ -493,6 +493,15 @@ dependencies = [
"serde_core", "serde_core",
] ]
[[package]]
name = "slotmap"
version = "1.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bdd58c3c93c3d278ca835519292445cb4b0d4dc59ccfdf7ceadaab3f8aeb4038"
dependencies = [
"version_check",
]
[[package]] [[package]]
name = "smallvec" name = "smallvec"
version = "1.15.1" version = "1.15.1"
@@ -664,6 +673,12 @@ dependencies = [
"wasm-bindgen", "wasm-bindgen",
] ]
[[package]]
name = "version_check"
version = "0.9.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
[[package]] [[package]]
name = "wasip2" name = "wasip2"
version = "1.0.1+wasi-0.2.4" version = "1.0.1+wasi-0.2.4"
@@ -750,6 +765,7 @@ name = "wfassoc-cdylib"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"cbindgen", "cbindgen",
"slotmap",
"thiserror", "thiserror",
"wfassoc", "wfassoc",
] ]

View File

@@ -12,6 +12,7 @@ crate-type = ["cdylib"]
[dependencies] [dependencies]
thiserror = { workspace = true } thiserror = { workspace = true }
wfassoc = { path="../wfassoc" } wfassoc = { path="../wfassoc" }
slotmap = "1.1.1"
[build-dependencies] [build-dependencies]
cbindgen = "0.29.0" cbindgen = "0.29.0"

View File

@@ -2,6 +2,7 @@ use std::cell::RefCell;
use std::ffi::{CString, c_char}; use std::ffi::{CString, c_char};
use thiserror::Error as TeError; use thiserror::Error as TeError;
mod object_pool;
mod last_error; mod last_error;
mod string_cache; mod string_cache;
mod wrapper; mod wrapper;
@@ -11,9 +12,12 @@ mod wrapper;
/// Error occurs in this crate. /// Error occurs in this crate.
#[derive(Debug, TeError)] #[derive(Debug, TeError)]
enum Error { enum Error {
/// Error occurs in wfassoc core. /// Error when parsing Schema into Program.
#[error("{0}")] #[error("{0}")]
Core(#[from] wfassoc::Error), ParseProgram(#[from] wfassoc::highlevel::ParseProgramError),
/// Error when operating Program.
#[error("{0}")]
Program(#[from] wfassoc::highlevel::ProgramError),
#[error("error occurs when parsing into C/C++ string")] #[error("error occurs when parsing into C/C++ string")]
CastIntoCStr(#[from] std::ffi::NulError), CastIntoCStr(#[from] std::ffi::NulError),
@@ -48,7 +52,7 @@ pub extern "C" fn WFGetLastError() -> *const c_char {
#[unsafe(no_mangle)] #[unsafe(no_mangle)]
pub extern "C" fn WFHasPrivilege() -> bool { pub extern "C" fn WFHasPrivilege() -> bool {
wfassoc::utilities::has_privilege() wfassoc::win32::utilities::has_privilege()
} }
#[unsafe(no_mangle)] #[unsafe(no_mangle)]

View File

@@ -0,0 +1,65 @@
//! 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))
}
pub fn delete(&mut self, token: Token) -> Result<(), Error> {
match self.objs.remove(Self::token_to_key(token)) {
Some(_) => Ok(()),
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)
}
}

View File

@@ -50,3 +50,10 @@ pub fn set_string_cache(msg: &str) {
pub fn get_string_cache() -> *const c_char { pub fn get_string_cache() -> *const c_char {
STRING_CACHE.with(|e| e.borrow().get_msg()) STRING_CACHE.with(|e| e.borrow().get_msg())
} }
/// Clear thread local string cache.
pub fn clear_string_cache() {
STRING_CACHE.with(|e| {
e.borrow_mut().clear_msg();
});
}