use std::cell::RefCell;
use super::Pools;
thread_local! {
static THREAD_POOLS: RefCell<Option<Pools>> = const { RefCell::new(None) };
}
pub fn set_thread_pools(pools: Pools) {
THREAD_POOLS.with(|p| {
*p.borrow_mut() = Some(pools);
});
}
pub fn get_thread_pools() -> Option<Pools> {
THREAD_POOLS.with(|p| p.borrow().clone())
}
pub fn thread_pools() -> Pools {
get_thread_pools()
.expect("Thread-local pools not initialized. Call init_thread_pools() or set_thread_pools() first.")
}
pub fn with_thread_pools<F, R>(f: F) -> R
where
F: FnOnce(&Pools) -> R,
{
THREAD_POOLS.with(|p| {
let pools = p.borrow();
let pools = pools.as_ref().expect(
"Thread-local pools not initialized. Call init_thread_pools() or set_thread_pools() first.",
);
f(pools)
})
}
pub fn clear_thread_pools() {
THREAD_POOLS.with(|p| {
*p.borrow_mut() = None;
});
}
pub fn has_thread_pools() -> bool {
THREAD_POOLS.with(|p| p.borrow().is_some())
}
pub fn with_temporary_pools<F, R>(pools: Pools, f: F) -> R
where
F: FnOnce() -> R,
{
let previous = get_thread_pools();
set_thread_pools(pools);
struct Cleanup(Option<Pools>);
impl Drop for Cleanup {
fn drop(&mut self) {
match self.0.take() {
Some(p) => set_thread_pools(p),
None => clear_thread_pools(),
}
}
}
let _cleanup = Cleanup(previous);
f()
}
#[cfg(test)]
pub mod tests {
use super::*;
use crate::value::column::pool::allocator::PoolAllocator;
#[test]
fn test_thread_local_basic() {
assert!(!has_thread_pools());
assert!(get_thread_pools().is_none());
let pools = Pools::default();
set_thread_pools(pools.clone());
assert!(has_thread_pools());
assert!(get_thread_pools().is_some());
let retrieved = thread_pools();
clear_thread_pools();
assert!(!has_thread_pools());
}
#[test]
fn test_with_thread_pools() {
let pools = Pools::default();
set_thread_pools(pools);
let result = with_thread_pools(|p| {
p.bool_pool().stats().available
});
assert_eq!(result, 0);
clear_thread_pools();
}
#[test]
fn test_temporary_pools() {
let pools1 = Pools::new(16);
set_thread_pools(pools1.clone());
assert!(has_thread_pools());
let pools2 = Pools::new(32);
let result = with_temporary_pools(pools2, || {
thread_pools().bool_pool().stats().available
});
assert!(has_thread_pools());
clear_thread_pools();
}
#[test]
fn test_temporary_pools_with_none() {
assert!(!has_thread_pools());
let pools = Pools::default();
with_temporary_pools(pools, || {
assert!(has_thread_pools());
});
assert!(!has_thread_pools());
}
#[test]
#[should_panic(expected = "Thread-local pools not initialized")]
fn test_thread_pools_panics_when_not_set() {
clear_thread_pools();
thread_pools(); }
}