`boost::asio` - 使特定函数不并行运行

问题描述 投票:0回答:1

我有一个异步函数,其中包含一个回调函数,可用作协程,与

asio
中的示例完全相同: https://github.com/chriskohlhoff/asio/blob/fa27820c05afd740fa2adc1ecfb9da5afe026443/asio/src/examples/cpp20/operations/c_callback_wrapper.cpp

在此示例中,基于 C 的 API 函数

read_input
async_read_input
包装,并且可以像这样使用:

co_await async_read_input("Enter your name", asio::use_awaitable);

问题是,我的

read_input
不是线程安全的(我从多个线程调用
io_context::run
)。据我了解,在这种情况下
asio::strand
应该是有用的,但我不知道如何。如果我做类似的事情

co_await async_read_input("Enter your name", asio::bind_executor(strand, asio::use_awaitable));

据我了解,它的做法与我想要的相反,使完成按一定顺序发生,同时仍然让

read_input
并行运行。如果我使用
post
/
dispatch
/
defer
(我什至知道如何/如果可能的话)我不能
co_await
它。我还想
co_await
它。

boost-asio
1个回答
0
投票

链不会阻止操作并发运行。事实上,这与 Asio 的整个设计背道而驰:它的存在是为了促进与(本质上)异步外设或服务的交互。实际上,许多异步操作只能同时运行,例如当它们发生在硬件中时。

可以使用链来避免并发启动操作,但这并不意味着您不会立即启动多个并发操作,除非您还确保先前的操作已提前完成。这通常意味着某种排队。

我认为您描述的应用程序归结起来是这样的:

  • 您的经典 API 不支持线程
  • 你的界面必须是线程感知的
  • 最简单的解决方案是在 API 包装器的“黑匣子”内实现classical线程同步(
    read_input
    ),这样世界其他地方就可以简单地将其视为真正的异步服务,只需延迟较高,具体取决于已挂起的调用数量。

非常简单地说,可能会转化为:

void read_input(char const* prompt, void (*cb)(void*, char const*), void* arg) {
    std::thread([prompt = std::string(prompt), cb, arg] {
        static std::mutex mx;
        std::string       line;
        {
            std::lock_guard lk(mx);
            std::cout << prompt << ": ";
            std::cout.flush();
            std::getline(std::cin, line);
        }
        cb(arg, line.c_str());
    }).detach();
}
© www.soinside.com 2019 - 2024. All rights reserved.