简体   繁体   English

在多线程程序中禁用 boost::asio 上的线程是否安全?

[英]Is it safe to disable threads on boost::asio in a multi-threaded program?

I read in this SO answer that there are locks around several parts of asio's internals.我在this SO answer中读到,asio内部的几个部分都有锁。

In addition I'm aware that asio is designed to allow multiple threads to service a single io_context .此外,我知道 asio 旨在允许多个线程为单个io_context提供服务。

However, if I only have a single thread servicing a single io_context , but I want to have more than 1 io_context in my application, is it safe to disable threads (per BOOST_ASIO_DISABLE_THREADS )但是,如果我只有一个线程为单个io_context提供服务,我想在我的应用程序中拥有超过 1 个io_context ,那么禁用线程是否安全(每个BOOST_ASIO_DISABLE_THREADS

That is: I have one io_context and one thread which has entered its io_context::run() loop, and it is servicing a number of sockets etc. All interaction with these sockets are done within the context of that thread.那就是:我有一个io_context和一个线程,它进入了它的io_context::run()循环,它正在为许多套接字等提供服务。与这些套接字的所有交互都是在该线程的上下文中完成的。

I then also have another thread, and another io_context , and that thread services that io_context and its sockets etc.然后我还有另一个线程和另一个io_context ,并且线程为io_context及其套接字等提供服务。

Inter-thread communication is achieved using a custom thread-safe queue and an eventfd wrapped with an asio::posix::stream_descriptor which is written to by the initiating thread, and read from the receiving thread which then pops items off the thread-safe queue.线程间通信是使用自定义线程安全队列和用asio::posix::stream_descriptor包装的eventfd实现的,由启动线程写入,并从接收线程读取,然后从线程安全弹出项目队列。

So at no point will there be user code which attempts to call asio functions from a thread which isn't associated with the io_context servicing its asio objects.因此,在任何时候都不会有用户代码尝试从与服务其 asio 对象的io_context的线程调用 asio 函数。

With the above use-case in mind, is it safe to disable threads in asio?考虑到上述用例,在 asio 中禁用线程是否安全?

It'll depend.这将取决于。 As far as I know it ought to be fine.据我所知应该没问题。 See below for caveats/areas of attention.有关注意事项/注意领域,请参见下文。

Also, you might want to take a step back and think about the objectives.此外,您可能想退后一步考虑目标。 If you're trying to optimize areas containing async IO, there may be quick wins that don't require such drastic measures.如果您正在尝试优化包含异步 IO 的区域,则可能会有不需要如此激烈措施的快速胜利。 That is not to say that there are certainly situations where I imagine BOOST_ASIO_DISABLE_THREADS will help squeeze just that little extra bit of performance out.这并不是说在某些情况下我BOOST_ASIO_DISABLE_THREADS将有助于挤出一点额外的性能。


Impact影响

What BOOST_ASIO_DISABLE_THREADS does is BOOST_ASIO_DISABLE_THREADS所做的是

  • replace selected mutexes/events with null implementations用空实现替换选定的互斥锁/事件
  • disable some internal thread support ( boost::asio::detail::thread throws on construction)禁用一些内部线程支持( boost::asio::detail::thread在构造时抛出)
  • removes atomics (atomic_count becomes non-atomic)删除原子(atomic_count 变为非原子)
  • make globals behave as simple statics (applies to system_context/system_executor)使全局变量表现为简单的静态变量(适用于 system_context/system_executor)
  • disables TLS support禁用 TLS 支持

System executor系统执行者

It's worth noting that system_executor is the default fallback when querying for associated handler executors.值得注意的是system_executor是查询关联的处理程序执行程序时的默认后备。 The library implementation specifies that async initiations will override that default with the executor of any IO object involved (eg the one bound to your socket or timer).库实现指定异步启动将使用任何涉及的 IO 对象(例如绑定到您的套接字或计时器的对象)的执行程序覆盖该默认值。

However, you have to scrutinize your own use and that of third-party code to make sure you don't accidentally rely on fallback.但是,您必须仔细检查自己的使用和第三方代码的使用,以确保您不会意外依赖回退。

Update: turns out system_executor internally spawns a thread_group which uses detail::thread - correctly erroring out when used更新:原来 system_executor 在内部产生了一个使用detail::thread的 thread_group - 使用时正确出错

IO Services IO 服务

Asio is extensible. Asio 是可扩展的。 Some services may elect to run internal threads as an implementation detail.一些服务可能会选择运行内部线程作为实现细节。

docs : 文档

The implementation of this library for a particular platform may make use of one or more internal threads to emulate asynchronicity.该库针对特定平台的实现可以利用一个或多个内部线程来模拟异步性。 As far as possible, these threads must be invisible to the library user.这些线程必须尽可能对库用户不可见。 [...] [...]

I'd trust the library implementation to use detail::thread - causing a runtime error if that were to be the case.我相信库实现会使用detail::thread - 如果是这种情况会导致运行时错误。

However, again, when using third-party code/user services you'll have to make sure that they don't break your assumptions.但是,同样,在使用第三方代码/用户服务时,您必须确保它们不会破坏您的假设。

Also, specific operations will not work without the thread support , like:此外, 如果没有线程支持,特定操作将无法工作,例如:

Live On Coliru住在科利鲁

#define BOOST_ASIO_DISABLE_THREADS
#include <boost/asio.hpp>
#include <iostream>

int main() {
    boost::asio::io_context ioc;
    boost::asio::ip::tcp::resolver r{ioc};

    std::cout << r.resolve("127.0.0.1", "80")->endpoint() << std::endl; // fine

    // throws "thread: not supported":
    r.async_resolve("127.0.0.1", "80", [](auto...) {});
}

Prints印刷

127.0.0.1:80
terminate called after throwing an instance of 'boost::wrapexcept<boost::system::system_error>'
  what():  thread: Operation not supported [system:95]
bash: line 7: 25771 Aborted                 (core dumped) ./a.out

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM