Lou*_* Go 2 c++ multithreading initialization c++11
编辑:这是一个 XY 问题,但也保留原始标题。它可能会帮助其他有相同 XY 问题的人。目标应该是:“有std::once_flag任务成功完成后才翻转”。
我如何不使用g_init(在下面的示例中)同时避免filesystem::exists()?
cfg["PATH"]未知,只能由调用者提供。欢迎C++20或C++23等解决方案。最好是标准或自制解决方案。也可能是XY问题......
简化的演示
#include <mutex>
#include <filesystem>
#include <atomic>
#include "fmt/core.h"
#include "nlohmann/json.hpp"
using json = nlohmann::json;
std::once_flag g_flag;
std::atomic<bool> g_init{false};
void doOnce(std::string path){
// initializing from file...
fmt::print("initialization done");
}
void doWork(json& cfg){
// Atomic flag for
if(g_init) {
fmt::print("already inited");
return;
}
std::string path = cfg["PATH"];
if(!std::filesystem::exists(path)){
fmt::print("load failed");
return;
}
std::call_once(g_flag, doOnce, path);
}
int main() {
json cfg;
cfg["PATH"] = "/opt/usr/foo";
// In the real world case, caller will call it
// with random values and PATH might not exist.
doWork(cfg);
}
Run Code Online (Sandbox Code Playgroud)
似乎std::once_flag没有暴露任何东西来知道它是否被调用。
call_once这正是应该解决的问题。如果你让它完成它的工作,它会为你处理所有这一切。如果初始化失败时抛出异常call_once将再次运行:
void doOnce(std::string path){
if(!std::filesystem::exists(path)){
throw std::runtime_error("load failed");
}
// initializing from file...
fmt::print("initialization done");
}
void doWork(json& cfg){
std::string path = cfg["PATH"];
try
{
std::call_once(g_flag, doOnce, path);
}
catch (std::exception& ex)
{
fmt::print(ex.what());
}
}
Run Code Online (Sandbox Code Playgroud)