feat: add object pool for cdylib
This commit is contained in:
16
Cargo.lock
generated
16
Cargo.lock
generated
@@ -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",
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|||||||
@@ -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)]
|
||||||
|
|||||||
65
wfassoc-cdylib/src/object_pool.rs
Normal file
65
wfassoc-cdylib/src/object_pool.rs
Normal 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)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user