std::call_once可以重置吗?
Can std::call_once be reset?
我刚才写了一个函数,基于 Unreal Engine 4's blueprint implementation,它只调用一次可调用对象,直到它被重置:
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;
}
}
今天我了解到 std::call_once
存在,跨线程工作,使用有参数的可调用对象,测试异常安全性,并且基本上像我一样环绕 std::invoke
(至少 MSVC 实现).
这听起来不错,而且在可能的情况下,我更喜欢调用预先存在的函数而不是编写自己的函数。
就像 Unreal 的文档所建议的那样,有时我可能需要通过重置内部标志来再次调用可调用对象; 是否可以重置 std::call_once
以允许再次调用底层可调用对象?
当他们称其为“once_flag”时,标准并不是在开玩笑。这是一个只设置一次的标志。
您当然可以使用 不同 个一次性标志对象多次调用该函数。但是要正确地做到这一点,您需要将每个可能尝试调用它的线程交给新的一次性标志对象。它不能只是某处的全局或静态对象;您必须实际将每个新调用编组到所有想要调用它的线程。
我刚才写了一个函数,基于 Unreal Engine 4's blueprint implementation,它只调用一次可调用对象,直到它被重置:
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;
}
}
今天我了解到 std::call_once
存在,跨线程工作,使用有参数的可调用对象,测试异常安全性,并且基本上像我一样环绕 std::invoke
(至少 MSVC 实现).
这听起来不错,而且在可能的情况下,我更喜欢调用预先存在的函数而不是编写自己的函数。
就像 Unreal 的文档所建议的那样,有时我可能需要通过重置内部标志来再次调用可调用对象; 是否可以重置 std::call_once
以允许再次调用底层可调用对象?
当他们称其为“once_flag”时,标准并不是在开玩笑。这是一个只设置一次的标志。
您当然可以使用 不同 个一次性标志对象多次调用该函数。但是要正确地做到这一点,您需要将每个可能尝试调用它的线程交给新的一次性标志对象。它不能只是某处的全局或静态对象;您必须实际将每个新调用编组到所有想要调用它的线程。