Boost C++ 库

…世界上评价最高、设计最精良的 C++ 库项目之一。 Herb SutterAndrei Alexandrescu, 《C++ 编码标准》

运行时配置和并发提示 - Boost C++ 函数库
PrevUpHomeNext

Boost.Asio 提供了一些运行时配置选项,可用于微调 Boost.Asio 的行为,例如启用或禁用特定的优化。可用的配置选项列在下表中。

章节

类型

Default

描述

scheduler

concurrency_hint

int

0

这是向 io_context 实现提出的建议,关于应使用多少个活动线程来运行完成处理程序。

当使用 Windows I/O 完成端口后端时,此值会传递给 CreateIoCompletionPort

当使用基于 reactor 的后端时,实现会识别值 1 作为 io_context 将从单个线程运行的指示,并基于此假设应用几项优化。例如,当一个处理程序从另一个处理程序内部发布时,新的处理程序将被添加到快速的线程本地队列中(其后果是新的处理程序将被延迟,直到当前正在执行的处理程序完成)。

无论为此配置选项指定什么值,io_contextthread_pool 仍然提供完全的线程安全,并且可以在任何线程中使用不同的 I/O 对象。

scheduler

locking

bool

true

当使用基于 reactor 的后端时,这用于启用或禁用调度器中的锁定。当设置为 false 时,此选项有以下限制:

— 必须小心确保对 io_context 及其任何关联的 I/O 对象(如套接字和计时器)的所有操作一次只能在一个线程中发生。

— 异步解析操作将以 operation_not_supported 失败。

— 如果 signal_setio_context 一起使用,则 signal_set 对象不能与程序中的任何其他 io_context 一起使用。

scheduler

locking_spin_count

int

0

当使用基于 reactor 的后端时,第一次尝试获取调度器内部锁而不阻塞的次数。

scheduler

task_usec

int

-1

调度器等待其 reactor 任务完成的最长时间(以微秒为单位)。值为 -1 表示对此等待时间没有限制。可以设置为 0 以启用 CPU 密集型旋转。

scheduler

wait_usec

int

-1

调度器在空闲线程(即未执行处理程序或等待 reactor 的线程)中等待唤醒事件的最长时间(以微秒为单位)。值为 -1 表示对此等待时间没有限制。可以设置为 0 以在多线程运行的执行上下文中启用 CPU 密集型旋转。

reactor

preallocated_io_objects

unsigned int

0

构造时分配的内部 reactor I/O 对象状态的数量。

reactor 实现使用每个 I/O 对象的状态来跟踪未完成操作的队列等内容。这些状态对象在 I/O 对象销毁后会被回收,但如果没有可用的未使用状态对象,则会分配新的状态对象。

如果在构造时已知 I/O 对象的上限,则可以设置此配置选项以确保构造完成后不会发生分配。

reactor

registration_locking

bool

true

在 I/O 对象注册和注销期间,启用或禁用 reactor 中的锁定。

如果设置为 false,则必须小心,避免并发打开或关闭 I/O 对象。

reactor

registration_locking_spin_count

int

0

在执行 I/O 对象注册或注销时,第一次尝试获取 reactor 锁而不阻塞的次数。

reactor

io_locking

bool

true

在 reactor 中启用或禁用每个 I/O 对象的锁定。

如果设置为 false,则必须小心,确保 io_context运行函数(即 runrun_forrun_untilrun_onerun_one_forrun_one_untilpollpoll_one),以及上下文的关联 I/O 对象(如套接字和计时器)的所有操作,一次只能在一个线程中发生。

reactor

io_locking_spin_count

int

0

第一次尝试获取 reactor 的每个 I/O 对象锁而不阻塞的次数。

timer

heap_reserve

unsigned int

0

在内部计时器队列堆中保留的条目数。

如果在构造时已知计时器的上限,则可以设置此配置选项以确保构造完成后不会发生计时器分配。

resolver

threads

unsigned int

0

用于异步名称解析的内部线程数。

如果非零,则在构造第一个解析器对象时创建指定数量的线程。否则,在第一次 async_resolve 调用时最多创建一个线程。

这些配置选项与执行上下文(如 io_contextthread_pool)相关联。为了使用非默认值,必须在构造时将配置服务安装到执行上下文中。下面几节将说明实现此目的的几种方法。

从字符串配置

要从字符串读取配置选项,请使用 config_from_string 对象构造执行上下文。

boost::asio::io_context my_io_context{
    boost::asio::config_from_string{
      "scheduler.concurrency_hint=10\n"
      "scheduler.locking=1"}};

每个变量必须单独占一行,格式为:

section.key=value

或者,如果指定了可选前缀:

prefix.section.key=value

空白行和以 # 开头的行将被忽略。也允许在值后面包含以 # 开头的注释。

从环境变量配置

要从环境变量读取配置选项,请使用 config_from_env 对象构造执行上下文。

boost::asio::io_context my_io_context{
    boost::asio::config_from_env{"my_app"}};

环境变量名是通过连接前缀、节和键,并使用下划线作为分隔符,然后将生成的字符串转换为大写来形成的。例如,给定一个前缀 "my_app""scheduler" / "concurrency_hint" 选项,其值将从名为 MY_APP_SCHEDULER_CONCURRENCY_HINT 的环境变量中读取。

从并发提示配置

为了向后兼容,可以向 io_context 构造函数传递一个整数作为并发提示。这用于初始化配置选项,如下面的表格所示。

concurrency_hint 值

效果

n,其中 n < 0xFFFF

等同于设置:

"scheduler" / "concurrency_hint"n

"scheduler" / "locking"true

"reactor" / "registration_locking"true

"reactor" / "io_locking"true

BOOST_ASIO_CONCURRENCY_HINT_UNSAFE

"scheduler" / "concurrency_hint"1

"scheduler" / "locking"false

"reactor" / "registration_locking"false

"reactor" / "io_locking"false

BOOST_ASIO_CONCURRENCY_HINT_UNSAFE_IO

"scheduler" / "concurrency_hint"1

"scheduler" / "locking"true

"reactor" / "registration_locking"true

"reactor" / "io_locking"false

BOOST_ASIO_CONCURRENCY_HINT_SAFE

"scheduler" / "concurrency_hint"0

"scheduler" / "locking"true

"reactor" / "registration_locking"true

"reactor" / "io_locking"true

默认构造的 io_context 对象使用的并发提示可以通过在编译时定义 BOOST_ASIO_CONCURRENCY_HINT_DEFAULT 宏来覆盖。例如,在编译器命令行中指定

-DBOOST_ASIO_CONCURRENCY_HINT_DEFAULT=1

意味着程序中所有默认构造的 io_context 对象都使用并发提示 1。类似地,使用 1 构造的 io_context 对象使用的并发提示可以通过定义 BOOST_ASIO_CONCURRENCY_HINT_1 来覆盖。例如,传递

-DBOOST_ASIO_CONCURRENCY_HINT_1=BOOST_ASIO_CONCURRENCY_HINT_UNSAFE

给编译器将禁用所有这些对象的线程安全。

自定义配置选项

应用程序和第三方库可以利用 config 类将自己的配置选项与执行上下文关联起来,或者访问上面列出的配置选项。通过将节、键和默认值传递给 get 成员函数来访问配置参数的值。

boost::asio::config cfg{ctx};
bool enable_locking = cfg.get("scheduler", "locking", true);

PrevUpHomeNext