代码之家  ›  专栏  ›  技术社区  ›  Tamás Szelei

从超时std::future中检索标识符?

  •  1
  • Tamás Szelei  · 技术社区  · 7 年前

    我有一个异步执行器,它向具有id的服务器发送请求。服务器执行请求,执行器将能够识别工作项 promise 来自响应中相同的id值。请求可能超时。在这种情况下,我希望执行者完全删除此请求的ID。然而,当未来超时并且服务器没有ID时,我不知道如何识别这个承诺。

    为了简洁起见,我发布了一个简化的示例。

    struct Executor {
        std::map<work_id_t, std::promise<Result>> work_items;
    };
    
    // run requests asynchronously
    std::future<Result> Executor::post_work(Request r, work_id_t id) {
        work_items[id] = std::promise<Result>();
        do_request(w);
        return work_items[id].get_future();
    }
    
    // called when a requests finishes (the server supplies the id)
    void Executor::work_finished(work_id_t id, Result r) {
        work_items[id].set_value(r);
        work_items.erase(id);
    }
    
    // ...
    
    Executor e;
    auto ft = e.post_work(Request("foo"));    
    auto wait_result = ft.wait_for(timeout_value);
    if (wait_result == std::future_status::timeout) {
        e.remove_item(???); // what can I pass here?
    }
    

    我如何实现 remove_item 发生超时时的函数?或者,我如何更改设计以允许类似的机制?

    1 回复  |  直到 7 年前
        1
  •  1
  •   Steve Lorimer    7 年前

    从您提供的界面来看 work_id_t 在呼叫中可用 Executor::post_work

    因此,由于调用方在超时的情况下需要id,因此只需从 post_work

    也许可以将其包装在结构中,例如:

    struct Work {
        std::future<Result> ft;
        work_id_t id;
    };
    

    Work 实例来自 执行人::post_工作 ,然后您可以等待将来,在超时的情况下,使用id删除该项目

    Work w = ...
    auto wait_result = w.ft.wait_for(timeout_value);
    if (wait_result == std::future_status::timeout) {
        e.remove_item(w.id);
    }
    

    在您的示例中:

    struct Executor {
        std::map<work_id_t, std::promise<Result>> work_items;
    };
    
    struct Work {
        std::future<Result> ft;
        work_id_t id;
    };
    
    // run requests asynchronously
    Work Executor::post_work(Request r, work_id_t id) {
        work_items[id] = std::promise<Result>();
        do_request(w);
        return { work_items[id].get_future(), id };
    }
    
    // called when a requests finishes (the server supplies the id)
    void Executor::work_finished(work_id_t id, Result r) {
        work_items[id].set_value(r);
        work_items.erase(id);
    }
    
    // ...
    
    Executor e;
    Work w = e.post_work(Request("foo"));    
    auto wait_result = w.ft.wait_for(timeout_value);
    if (wait_result == std::future_status::timeout) {
        e.remove_item(w.id);
    }