gpt4 book ai didi

c++ - 知道使用 std::once_flag 而不调用 std::call_once (任务成功完成后设置once_flag)

转载 作者:行者123 更新时间:2023-12-03 07:53:13 27 4
gpt4 key购买 nike

编辑:这是一个 XY 问题,但也保留原始标题。它可能会帮助其他有相同 XY 问题的人。目标应该是:“仅在任务成功完成后才翻转 std::once_flag。”

用例

  1. 初始化只需完成一次,并且可能会同时调用。
  2. 在调用初始化之前,需要完成验证。
  3. 如果已经初始化,则不需要验证。

问题

如何在初始化后避免使用 g_init(在下面的示例中),同时避免 filesystem::exists() 检查?

限制

  1. 我无法修改调用者,这是我无法更改的基础设施。
  2. cfg["PATH"] 未知,只能由调用者提供。

欢迎使用 C++20 或 C++23 等解决方案。最好是标准或自制解决方案。也可能是 XY 问题...

简化的demo

#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);
}

看来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());
}
}

关于c++ - 知道使用 std::once_flag 而不调用 std::call_once (任务成功完成后设置once_flag),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/76634121/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com