gpt4 book ai didi

c++ - 设计一个结合了同步和异步操作的 C++ API

转载 作者:太空狗 更新时间:2023-10-29 22:58:28 25 4
gpt4 key购买 nike

关闭。这个问题不满足Stack Overflow guidelines .它目前不接受答案。












想改善这个问题吗?更新问题,使其成为 on-topic对于堆栈溢出。

5年前关闭。




Improve this question




我正在设计一个公开同步和异步操作的 C++ API。所有操作都可能失败,必须报告失败。异步操作必须提供一种在完成时执行延续的方法。我试图以最易读和一致的方式设计 API。

这是一个示例,说明我现在的设计:

#include <memory>
#include <future>

using namespace std;

class Error {
public:
Error(int c, string desc) : code(c), description(desc) {}

int code;
string description;
};

template<typename T>
class Callback {
public:
virtual void completed(const T& result, unique_ptr<Error> error) = 0;
};

template<typename T>
class PrintCallback : public Callback<T> {
public:
void completed(const T& result, unique_ptr<Error> error) override {
if (nullptr != error) {
printf("An error has occured. Code: %d Description: %s\n",
error->code, error->description.c_str());
} else {
printf("Operation completed successfully. Result: %s\n",
to_string(result).c_str());
}
}
};

class API {
public:
void asyncOperation(shared_ptr<Callback<int>> callback) {
thread([callback]() {
callback->completed(5, nullptr);
}).detach();
}

int syncOperation(unique_ptr<Error>& error) {
return 5;
}

void asyncFailedOperation(shared_ptr<Callback<int>> callback) {
thread([callback]() {
callback->completed(-1, unique_ptr<Error>(new Error(222, "Async Error")));
}).detach();
}

int syncFailedOperation(unique_ptr<Error>& error) {
error = unique_ptr<Error>(new Error(111, "Sync Error"));
return -1;
}
};

我不喜欢在同步操作中使用错误输出参数以及同步和异步签名之间的不一致。
我正在讨论两种选择:
  • 将同步操作视为异步操作,并让它们接受回调以返回结果/失败。这种方法在同步和异步操作中更加一致,看起来更简洁。另一方面,让一个简单的同步操作与回调一起工作感觉有点奇怪。
  • 使用 std::promisestd::future ,并使用异常报告失败。对于异步操作,std::future将返回其 get()会在失败的情况下抛出。同步操作将在失败的情况下简单地抛出。这种方法感觉更简洁,因为错误处理不会破坏方法签名,并且异常是在 C++ 中进行错误处理的标准方法。但是,要获得结果,我必须调用 future::get()所以如果我不想阻塞,那么我必须启动另一个线程来等待结果。异步操作的继续运行在实际将结果设置在 std::promise 上的线程上也很重要。 .这种方法是这个问题的公认答案 - Synchronous and ASynchronous APIs .

  • 我很好奇:
  • 如果可以避免替代#2 中的额外线程。
  • 如果替代方案 #2 的缺点超过其优点(尤其是额外的线程)。
  • 如果还有其他我没有考虑过的方法。
  • 哪种方法被认为是可读性和一致性的最佳选择。

  • 谢谢!

    最佳答案

  • 问:如果可以避免替代#2 中的额外线程。
  • 答:避免额外线程的一种方法是将线程池与任务队列一起使用。该方法仍然使用额外的线程,但线程的数量在某种程度上是固定的系统明智的,而不是与曾经创建的任务数量成正比。
  • 问:如果替代方案 #2 的缺点大于其优点(尤其是额外的线程)。
  • 答:我不这么认为。
  • 问:如果有另一种方法我没有考虑过。
  • 答:是的。在我看来,最好的方法是让一切都异步,提供与 boost::asio 类似的 API,利用 boost::asio::io_service 和 lambda 函数,并实现线程池和任务队列。您可以将同步实现为异步的包装器,如下所示:进行异步调用并等待 std::condition_variable。您的异步调用的回调表示 condition_variable。
  • 问:哪种方法被认为是可读性和一致性的最佳选择。
  • 答:异步代码不会像同步代码那样可读。如果可读性对您来说真的很重要,请放弃异步。另一方面,如果您想要异步和一致性,请按照我上面概述的方式将所有内容设为异步。

  • 除此之外,在我看来,您不应该实现自己的 Error 类。看看 std::error_code (还有 error_condition、error_category)。一篇不错的文章是 http://blog.think-async.com .已经有人替你想好了。

    关于c++ - 设计一个结合了同步和异步操作的 C++ API,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40490235/

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