源码
先附上可用于学习的开源代码: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实现比较简单,感兴趣可以自行实现试试看