aether/engine/pool.rs
1//! 引擎池模式
2//!
3//! 使用线程局部存储管理引擎池,每个线程维护独立的引擎池。
4//! 适合单线程内高频调用场景,需要比 GlobalEngine 更多的引擎实例。
5//!
6//! **注意**:由于 Aether 使用 `Rc`(非线程安全),引擎池是线程局部的。
7//! 每个线程有独立的引擎池,线程间不共享。
8
9use crate::{Aether, Value};
10
11/// 线程局部引擎池
12///
13/// # 使用场景
14///
15/// - ✅ 单线程内需要多个引擎实例
16/// - ✅ 避免频繁创建引擎的开销
17/// - ✅ 需要环境隔离的高频调用
18/// - ⚠️ 每个线程有独立的池(不跨线程共享)
19///
20/// # 特点
21///
22/// - **线程局部**:每个线程有独立的引擎池
23/// - **自动管理**:RAII模式,使用完自动归还
24/// - **环境隔离**:每次获取前清空变量
25/// - **AST缓存**:每个引擎独立维护缓存
26///
27/// # 示例
28///
29/// ```rust
30/// use aether::engine::EnginePool;
31///
32/// // 创建线程局部引擎池
33/// let pool = EnginePool::new(4);
34///
35/// // 使用引擎
36/// {
37/// let mut engine = pool.acquire();
38/// let result = engine.eval("Set X 10\n(X + 20)").unwrap();
39/// println!("Result: {}", result);
40/// } // engine 自动归还到池中
41///
42/// // 多次使用(复用引擎实例)
43/// for i in 0..100 {
44/// let mut engine = pool.acquire();
45/// let code = format!("Set X {}\n(X * 2)", i);
46/// engine.eval(&code).unwrap();
47/// }
48/// ```
49///
50/// # 与 GlobalEngine 对比
51///
52/// - **GlobalEngine**: 单个引擎实例,适合简单场景
53/// - **EnginePool**: 多个引擎实例,避免频繁创建开销
54///
55/// 如果你只需要一个引擎实例,使用 `GlobalEngine` 更简单。
56pub struct EnginePool {
57 engines: Vec<Aether>,
58 available: Vec<bool>,
59}
60
61impl EnginePool {
62 /// 创建新的引擎池
63 ///
64 /// # 参数
65 ///
66 /// - `capacity`: 池大小
67 ///
68 /// # 示例
69 ///
70 /// ```rust
71 /// use aether::engine::EnginePool;
72 ///
73 /// // 创建容量为4的引擎池
74 /// let pool = EnginePool::new(4);
75 /// ```
76 pub fn new(capacity: usize) -> Self {
77 let mut engines = Vec::with_capacity(capacity);
78 let available = vec![true; capacity];
79
80 // 预创建引擎实例
81 for _ in 0..capacity {
82 engines.push(Aether::new());
83 }
84
85 Self { engines, available }
86 }
87
88 /// 从池中获取引擎(自动归还)
89 ///
90 /// 如果池中没有可用引擎,会创建临时引擎。
91 /// 返回的 `PooledEngine` 会在作用域结束时自动归还到池中。
92 ///
93 /// # 环境隔离
94 ///
95 /// 每次获取前自动清空环境变量,保证隔离性。
96 pub fn acquire(&mut self) -> PooledEngine {
97 // 查找可用引擎
98 for (i, &is_available) in self.available.iter().enumerate() {
99 if is_available {
100 self.available[i] = false;
101 let mut engine = std::mem::take(&mut self.engines[i]);
102
103 // 重置环境(保证隔离性)
104 engine.evaluator.reset_env();
105
106 return PooledEngine {
107 engine: Some(engine),
108 pool_index: Some(i),
109 pool: self as *mut Self,
110 };
111 }
112 }
113
114 // 池中无可用引擎,创建临时引擎
115 let engine = Aether::new();
116 PooledEngine {
117 engine: Some(engine),
118 pool_index: None,
119 pool: std::ptr::null_mut(),
120 }
121 }
122
123 /// 归还引擎到池中
124 fn return_engine(&mut self, index: usize, engine: Aether) {
125 self.engines[index] = engine;
126 self.available[index] = true;
127 }
128
129 /// 获取池的容量
130 pub fn capacity(&self) -> usize {
131 self.engines.len()
132 }
133
134 /// 获取池中当前可用的引擎数量
135 pub fn available(&self) -> usize {
136 self.available.iter().filter(|&&x| x).count()
137 }
138}
139
140/// 自动归还的引擎(RAII模式)
141///
142/// 当此对象离开作用域时,引擎会自动归还到池中。
143pub struct PooledEngine {
144 engine: Option<Aether>,
145 pool_index: Option<usize>,
146 pool: *mut EnginePool,
147}
148
149impl PooledEngine {
150 /// 执行 Aether 代码
151 ///
152 /// # 参数
153 ///
154 /// - `code`: 要执行的代码
155 ///
156 /// # 返回
157 ///
158 /// - `Ok(Value)`: 执行结果
159 /// - `Err(String)`: 错误信息
160 pub fn eval(&mut self, code: &str) -> Result<Value, String> {
161 self.engine.as_mut().unwrap().eval(code)
162 }
163
164 /// 获取AST缓存统计信息
165 pub fn cache_stats(&self) -> crate::cache::CacheStats {
166 self.engine.as_ref().unwrap().cache_stats()
167 }
168
169 /// 清空AST缓存
170 pub fn clear_cache(&mut self) {
171 self.engine.as_mut().unwrap().clear_cache();
172 }
173
174 /// 配置优化选项
175 pub fn set_optimization(
176 &mut self,
177 constant_folding: bool,
178 dead_code: bool,
179 tail_recursion: bool,
180 ) {
181 self.engine
182 .as_mut()
183 .unwrap()
184 .set_optimization(constant_folding, dead_code, tail_recursion);
185 }
186
187 /// 异步执行 Aether 代码(requires "async" feature)
188 ///
189 /// # 示例
190 ///
191 /// ```no_run
192 /// use aether::engine::EnginePool;
193 ///
194 /// #[tokio::main]
195 /// async fn main() {
196 /// let mut pool = EnginePool::new(4);
197 /// let mut engine = pool.acquire();
198 /// let result = engine.eval_async("Set X 10\n(X + 20)").await.unwrap();
199 /// println!("Result: {}", result);
200 /// }
201 /// ```
202 #[cfg(feature = "async")]
203 pub async fn eval_async(&mut self, code: &str) -> Result<Value, String> {
204 tokio::task::yield_now().await;
205 self.eval(code)
206 }
207}
208
209impl Drop for PooledEngine {
210 fn drop(&mut self) {
211 if let Some(engine) = self.engine.take()
212 && let Some(index) = self.pool_index
213 {
214 // 归还到池中
215 unsafe {
216 if !self.pool.is_null() {
217 (*self.pool).return_engine(index, engine);
218 }
219 }
220 }
221 // 否则是临时引擎,直接丢弃
222 }
223}
224
225#[cfg(test)]
226mod tests {
227 use super::*;
228
229 #[test]
230 fn test_pool_single_thread() {
231 let mut pool = EnginePool::new(2);
232
233 // 第一次获取
234 {
235 let mut engine = pool.acquire();
236 let result = engine.eval("Set X 10\n(X + 20)").unwrap();
237 assert_eq!(result.to_string(), "30");
238 }
239
240 // 第二次获取(环境应该是干净的)
241 {
242 let mut engine = pool.acquire();
243 let result = engine.eval("X");
244 assert!(result.is_err()); // X 不应该存在
245 }
246 }
247
248 #[test]
249 fn test_pool_multiple_acquire() {
250 let mut pool = EnginePool::new(2);
251
252 // 多次获取和使用
253 for i in 0..10 {
254 let mut engine = pool.acquire();
255 let code = format!("Set X {}\n(X * 2)", i);
256 let result = engine.eval(&code).unwrap();
257 assert_eq!(result.to_string(), format!("{}", i * 2));
258 }
259 }
260
261 #[test]
262 fn test_pool_auto_return() {
263 let mut pool = EnginePool::new(2);
264
265 assert_eq!(pool.available(), 2);
266
267 let _engine1 = pool.acquire();
268 assert_eq!(pool.available(), 1);
269
270 {
271 let _engine2 = pool.acquire();
272 assert_eq!(pool.available(), 0);
273 } // engine2 归还
274
275 assert_eq!(pool.available(), 1);
276 }
277}