【发布时间】:2021-12-23 09:22:34
【问题描述】:
asio::io_context 构造函数采用可选的concurrency hint,当只有单个线程将与io_context 或关联的 IO 对象交互(或线程之间的同步已在调用代码中完成)时,它会跳过一些内部锁。
我的理解是1 将允许我在一个线程中调用io_context::run() 并与io_context 正常交互(即,除reset() 和run()、run_one() 等之外的所有方法)和所有关联的 IO 对象。
另外,对于ASIO_CONCURRENCY_HINT_UNSAFE_IO,调用IO对象(下例中的数字3)上的任何IO方法都是非法的,而使用ASIO_CONCURRENCY_HINT_UNSAFE调用io_context本身的任何方法都是非法的。这是正确的吗?
#include <asio/io_context.hpp>
#include <asio/ip/tcp.hpp>
#include <chrono>
#include <iostream>
#include <thread>
static const char msg[] = "Hello World\n";
int main() {
const auto concurrency_hint = ASIO_CONCURRENCY_HINT_1;
asio::io_context ctx{concurrency_hint};
asio::ip::tcp::acceptor acc(ctx, asio::ip::tcp::endpoint(asio::ip::address_v4::any(), 7999));
acc.listen(2);
asio::ip::tcp::socket peer(ctx);
acc.async_accept(peer, [&peer](const asio::error_code &error) {
// call async methods from the thread running the io context (1)
peer.async_write_some(
asio::const_buffer(msg, 12), [&](const asio::error_code &error, std::size_t len) {
peer.close();
});
});
std::thread io_thread([&ctx]() { ctx.run(); });
// call `post()` from another thread (2)
asio::post([]() { std::cout << msg << std::flush; });
// call `async_accept` for an IO object running on another thread (3)
acc.async_accept([&](const asio::error_code &error, asio::ip::tcp::socket peer) {
peer.close();
});
// call `run()` while another thread is already doing so (4)
ctx.run_for(std::chrono::seconds(2));
std::this_thread::sleep_for(std::chrono::seconds(5));
// Call `io_context::stop()` from another thread (5)
ctx.stop();
io_thread.join();
return 0;
}
1 |
UNSAFE |
UNSAFE_IO |
SAFE |
|
|---|---|---|---|---|
| IO methods, same thread (1) | ✔ | ✔ | ✔ | ✔ |
post() from another thread (2) |
✔ | ✖ | ✔ | ✔ |
| IO methods, another thread (3) | ✔? | ✖ | ✖ | ✔ |
run() from two threads (4) |
✖ | ✖ | ✖ | ✔ |
io_context::stop() from another thread (5) |
? | ✖ | ✖ | ✔ |
【问题讨论】:
-
学究式地
UNSAFE不允许来自其他线程的操作,它不允许来自其他线程的非同步操作。 -
@Frank 绝对正确,但如果我想这样做,我不妨提供另一个并发提示,以便 Asio 负责必要的同步。
-
不一定。例如,您可能有一个多线程设置/拆卸,但来自单个线程的大量
post()。理想情况下,您希望在post()组上进行同步,而不是让 asio 对它们中的每一个执行同步。 -
或者你有另一个共享资源已经同步的情况,使得内置的
io_context同步变得多余。因此,您正在同步,但不希望 Asio 为您完成。 -
所有优点,我已经添加了关于手动同步的说明。
标签: c++ multithreading boost-asio