【Chromium】Base库的AtExitManager

2024-04-19 18:06:33 浏览数 (2)

源码

先附上可用于学习的开源代码:Base库

喜欢可以帮忙Star一下

前言

编译:参考Base库即可

环境:Visual Studio 2022 - 17.8.3 v143 10.0.22621.0 C 17

AtExitManager

这个类提供了类似于 CRT 的 atexit() 的功能,但我们可以控制回调函数的执行时间。在 Windows 下,对于 DLL,它们在一个非常糟糕的时机和加载器锁定下发生。这个功能主要被 base::Singleton 使用。

退出执行注册任务的线程是构建AtExitManager实例的线程

使用方法很简单。在 main() 或 WinMain() 的早期范围内,在栈上创建一个 AtExitManager 对象:

代码语言:C 复制
int main(...) { 
  base::AtExitManager exit_manager;
}

当 exit_manager 对象超出范围时,所有注册的回调函数和单例析构函数都将被调用。

源码解析

老规矩先上源码和对其的注释:

代码语言:C 复制
class BASE_EXPORT AtExitManager {
public:
    typedef void (AtExitCallbackType)(void);

    AtExitManager();

    // 析构函数调用所有已注册的回调函数。在此之后不要尝试注册更多的回调函数。
    ~AtExitManager();

    // 注册指定的函数在退出时调用。回调函数的原型为 void func(void*)。
    static void RegisterCallback(AtExitCallbackType func, void* param);

    // 注册指定的任务在退出时调用。
    static void RegisterTask(base::OnceClosure task);

    // 按照 LIFO 的顺序调用使用 RegisterCallback 注册的函数。在调用此函数后仍然可以注册新的回调函数。
    static void ProcessCallbacksNow();

    // 禁用所有已注册的退出回调。仅在单进程模式下使用。
    static void DisableAllAtExitManagers();

protected:
    // 此构造函数允许即使已存在 AtExitManager 实例,也可以创建该实例。这仅用于测试!
    // AtExitManager 保存在全局堆栈上,并在销毁时将其移除。这允许您遮盖另一个 
AtExitManager。
    explicit AtExitManager(bool shadow);

private:
    base::Lock lock_;

    base::stackbase::OnceClosure stack_ GUARDED_BY(lock_);

#if DCHECK_IS_ON()
    bool processing_callbacks_ GUARDED_BY(lock_) = false;
#endif

    // 允许遮盖的管理器堆栈。
    AtExitManager* const next_manager_;

    DISALLOW_COPY_AND_ASSIGN(AtExitManager);
};

注意:

1、从源码可知,AtExitManager注册的函数只能是下面这种

代码语言:C 复制
void func(void*)

2、注册任务也是如此

代码语言:C 复制
int g_test_counter_1 = 0;
void ExpectParamIsCounter(void* param) {  
  EXPECT_EQ(&g_test_counter_1, param);
} 

base::AtExitManager::RegisterTask(
      base::BindOnce(&ExpectParamIsCounter, &g_test_counter_1));

示例代码

代码语言:C 复制
void AtExitTask(void* param) {
    L_TRACE(L"%s %d", __FUNCTIONW__, *static_cast<int*>(param));
}

base::AtExitManager at_exit;
int i = 1;
at_exit.RegisterCallback(&AtExitTask, &i);
at_exit.RegisterCallback(&AtExitTask, &i);
at_exit.ProcessCallbacksNow();

整个AtExitManager实现比较简单,感兴趣可以自行实现试试看

0 人点赞