reifydb_core/value/column/pool/
thread_local.rs1use std::cell::RefCell;
11
12use super::Pools;
13
14thread_local! {
15 static THREAD_POOLS: RefCell<Option<Pools>> = RefCell::new(None);
17}
18
19pub fn set_thread_pools(pools: Pools) {
21 THREAD_POOLS.with(|p| {
22 *p.borrow_mut() = Some(pools);
23 });
24}
25
26pub fn get_thread_pools() -> Option<Pools> {
29 THREAD_POOLS.with(|p| p.borrow().clone())
30}
31
32pub fn thread_pools() -> Pools {
34 get_thread_pools()
35 .expect("Thread-local pools not initialized. Call init_thread_pools() or set_thread_pools() first.")
36}
37
38pub fn with_thread_pools<F, R>(f: F) -> R
40where
41 F: FnOnce(&Pools) -> R,
42{
43 THREAD_POOLS.with(|p| {
44 let pools = p.borrow();
45 let pools = pools.as_ref().expect(
46 "Thread-local pools not initialized. Call init_thread_pools() or set_thread_pools() first.",
47 );
48 f(pools)
49 })
50}
51
52pub fn clear_thread_pools() {
54 THREAD_POOLS.with(|p| {
55 *p.borrow_mut() = None;
56 });
57}
58
59pub fn has_thread_pools() -> bool {
61 THREAD_POOLS.with(|p| p.borrow().is_some())
62}
63
64pub fn with_temporary_pools<F, R>(pools: Pools, f: F) -> R
67where
68 F: FnOnce() -> R,
69{
70 let previous = get_thread_pools();
71 set_thread_pools(pools);
72
73 struct Cleanup(Option<Pools>);
75 impl Drop for Cleanup {
76 fn drop(&mut self) {
77 match self.0.take() {
78 Some(p) => set_thread_pools(p),
79 None => clear_thread_pools(),
80 }
81 }
82 }
83 let _cleanup = Cleanup(previous);
84
85 f()
86}
87
88#[cfg(test)]
89mod tests {
90 use super::*;
91 use crate::value::column::pool::allocator::PoolAllocator;
92
93 #[test]
94 fn test_thread_local_basic() {
95 assert!(!has_thread_pools());
97 assert!(get_thread_pools().is_none());
98
99 let pools = Pools::default();
101 set_thread_pools(pools.clone());
102
103 assert!(has_thread_pools());
105 assert!(get_thread_pools().is_some());
106
107 let retrieved = thread_pools();
109 clear_thread_pools();
113 assert!(!has_thread_pools());
114 }
115
116 #[test]
117 fn test_with_thread_pools() {
118 let pools = Pools::default();
119 set_thread_pools(pools);
120
121 let result = with_thread_pools(|p| {
122 p.bool_pool().stats().available
124 });
125
126 assert_eq!(result, 0); clear_thread_pools();
130 }
131
132 #[test]
133 fn test_temporary_pools() {
134 let pools1 = Pools::new(16);
136 set_thread_pools(pools1.clone());
137 assert!(has_thread_pools());
138
139 let pools2 = Pools::new(32);
141 let result = with_temporary_pools(pools2, || {
142 thread_pools().bool_pool().stats().available
144 });
145
146 assert!(has_thread_pools());
148 clear_thread_pools();
152 }
153
154 #[test]
155 fn test_temporary_pools_with_none() {
156 assert!(!has_thread_pools());
158
159 let pools = Pools::default();
161 with_temporary_pools(pools, || {
162 assert!(has_thread_pools());
163 });
164
165 assert!(!has_thread_pools());
167 }
168
169 #[test]
170 #[should_panic(expected = "Thread-local pools not initialized")]
171 fn test_thread_pools_panics_when_not_set() {
172 clear_thread_pools();
173 thread_pools(); }
175}