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}