std::call_once 可以重置吗?

Cas*_*sey 4 c++ c++17 std-call-once

我不久前根据虚幻引擎 4 的蓝图实现编写了一个函数,该函数仅调用一次可调用函数,直到它被重置:

template<typename Callable>
void DoOnce(Callable&& f, bool reset = false, bool start_closed = false) noexcept {
    static bool once = start_closed;
    if(!once) {
        once = true;
        std::invoke(f);
    }
    if(reset) {
        once = false;
    }
}
Run Code Online (Sandbox Code Playgroud)

今天我了解到std::call_once存在,跨线程工作,使用带有参数的可调用对象,测试异常安全,并且基本上std::invoke像我一样进行包装(至少是 MSVC 实现)。

这听起来很棒,而且在可能的情况下,我更喜欢调用预先存在的函数而不是编写自己的函数。

就像虚幻的文档所暗示的那样,有时我可能需要通过重置内部标志来再次调用可调用对象;可以std::call_once重置以允许再次调用底层可调用对象吗?

Nic*_*las 5

当标准将其称为“once_flag”时,它并不是在开玩笑。这是一个只设置一次的标志。

当然,您可以使用不同的一次标志对象多次调用该函数。但要正确执行此操作,您需要将可能尝试调用新的一次标志对象的每个线程交给它。它不能只是某处的全局或静态对象;它还可以是全局或静态对象。您必须实际将每个新调用编组到所有想要调用它的线程。