# 对于Functor的解释

## Functor 文件夹作用

Functor文件夹用于存放所有功能性的类，包括VAD、PUNC、ASR、SPK等。

## Functor 类的定义

所有类应继承于**基类**`BaseFunctor`。

为了方便使用，我们对于**基类**的定义如下：

1. 函数内部使用的变量以单下划线开头，基类中包含：

    * _model: Dict 存放模型相关的配置和实例
    * _input_queue: Queue 监听的输入消息队列
    * _thread: Threading.Thread 运行的线程实例
    * _callback: List[Callable] 回调函数列表
    * _is_running: bool 线程运行状态标志
    * _stop_event: bool 停止事件标志
    * _status_lock: threading.Lock 状态锁，用于线程同步

2. 对于使用的模型，请从统一的 **模型管理类`ModelLoader`** 中获取，由模型管理类统一进行加载、缓存和释放，`_model`存放类型为`dict`。

3. 基类定义的核心方法：

    * `add_callback(callback: Callable)`: 添加结果处理的回调函数
    * `set_model(model: dict)`: 设置模型配置和实例
    * `set_input_queue(queue: Queue)`: 设置输入数据队列
    * `run()`: 启动处理线程（抽象方法）
    * `stop()`: 停止处理线程（抽象方法）
    * `_run()`: 线程运行的具体逻辑（抽象方法）
    * `_pre_check()`: 运行前的预检查（抽象方法）

## 派生类实现要求

1. 必须实现的抽象方法：
    * `_pre_check()`: 
        - 检查必要的配置是否完整（如模型、队列等）
        - 检查运行环境是否满足要求
        - 返回检查结果

    * `_run()`:
        - 实现具体的数据处理逻辑
        - 从 _input_queue 获取输入数据
        - 使用 _model 进行处理
        - 通过 _callback 返回处理结果

    * `run()`:
        - 调用 _pre_check() 进行预检查
        - 创建并启动处理线程
        - 设置相关状态标志

    * `stop()`:
        - 安全停止处理线程
        - 清理资源
        - 重置状态标志

2. 建议实现的方法：
    * `__str__`: 返回当前实例的状态信息
    * 错误处理方法：处理运行过程中的异常情况

## 使用示例

```python
class MyFunctor(BaseFunctor):
    def _pre_check(self):
        if not self._model or not self._input_queue:
            return False
        return True

    def _run(self):
        while not self._stop_event:
            try:
                data = self._input_queue.get(timeout=1.0)
                result = self._model['my_model'].process(data)
                for callback in self._callback:
                    callback(result)
            except Queue.Empty:
                continue
            except Exception as e:
                logger.error(f"处理错误: {e}")

    def run(self):
        if not self._pre_check():
            raise RuntimeError("预检查失败")
        
        with self._status_lock:
            if self._is_running:
                return
            self._is_running = True
            self._stop_event = False
            self._thread = threading.Thread(target=self._run)
            self._thread.start()

    def stop(self):
        with self._status_lock:
            if not self._is_running:
                return
            self._stop_event = True
            if self._thread:
                self._thread.join()
            self._is_running = False
```

## 注意事项

1. 线程安全：
    * 使用 _status_lock 保护状态变更
    * 注意共享资源的访问控制

2. 错误处理：
    * 在 _run() 中妥善处理异常
    * 提供详细的错误日志

3. 资源管理：
    * 确保在 stop() 中正确清理资源
    * 避免资源泄露

4. 回调函数：
    * 回调函数应该是非阻塞的
    * 处理回调函数抛出的异常