boost asio deadline timer

Рассмотрим этот короткий фрагмент кода, где один boost:: deadline_timer прерывает другое:

Если время для таймера 2 изменяется вокруг метки 2 секунды, иногда timer1_handler1 сообщает об успехе, а иногда и операции отменяется. Это, вероятно, определено в тривиальном примере, потому что мы знаем, в какое время установлен таймер2.

Это представляет собой более сложную систему, в которой таймер 1 реализует таймаут, а timer2 — действительно асинхронный сокет. Иногда я наблюдал сценарий, когда timer1 отменяется слишком поздно, и первый обработчик возвращается после вызова второй async_wait(), тем самым давая ложный тайм-аут.

Очевидно, мне нужно совместить обратные вызовы обработчика с соответствующим вызовом async_wait(). Есть ли удобный способ сделать это?

Вы можете boost::bind дополнительные параметры обработчику завершения, который может использоваться для идентификации источника.

Один удобный способ решения поставленной задачи, управление асинхронными операциями более высокого уровня, состоящий из нескольких несинхронных асинхронных операций, заключается в использовании подхода, используемого в официальном Boost timeout. Внутри этого процесса обработчики принимают решения, исследуя текущее состояние, а не логику обработчика связи с ожидаемым или предоставленным состоянием.

Прежде чем приступать к решению, важно определить все возможные случаи выполнения обработчика. Когда запускается io_service , одна итерация цикла событий выполняет все операции, которые готовы к запуску, и по завершении операции обработчик завершения пользователя помещается в очередь с error_code , указывающим состояние операции. Затем io_service вызовет обработчики завершения очереди. Следовательно, в одной итерации все готовые к запуску операции выполняются в неуказанном порядке до обработчиков завершения, а порядок, в котором задействованы обработчики завершения, не указан. Например, при составлении операции async_read_with_timeout() из async_read() и async_wait() , где любая операция отменяется только в другом обработчике завершения операции, возможен следующий случай:

  • async_read() и async_wait() не готов к запуску, затем вызывается async_read() обработчик завершения и отменяет async_wait() , заставляя обработчик завершения async_wait() запускать с ошибкой boost::asio::error::operation_aborted .
  • async_read() не готов к запуску, а async_wait() выполняется, затем вызывается async_wait() обработчик завершения и отменяет async_read() , заставляя обработчик завершения async_read() запускать с ошибкой boost::asio::error::operation_aborted .
  • async_read() и async_wait() запускается, тогда сначала запускается обработчик завершения async_read() , но операция async_wait() уже завершена и не может быть отменена, поэтому обработчик завершения async_wait() будет запущен без ошибок.
  • async_read() и async_wait() , тогда сначала запускается обработчик завершения async_wait() , но операция async_read() уже завершена и не может быть отменена, поэтому обработчик завершения async_read() будет запущен без ошибок.

Обработчик завершения error_code указывает состояние операции и не отражает изменения состояния в результате других обработчиков завершения; поэтому, когда error_code успешно, может потребоваться изучить текущее состояние для выполнения условного разветвления. Однако, прежде чем вводить дополнительное состояние, можно попытаться изучить цель операции более высокого уровня и какое состояние уже доступно. В этом примере давайте определим, что целью async_read_with_timeout() является закрытие сокета, если данные не были получены до того, как был достигнут крайний срок. Для состояния сокет является открытым или закрытым; таймер обеспечивает время истечения; и системные часы обеспечивают текущее время. После изучения цели и доступной информации о состоянии можно предложить:

  • async_wait() обработчик должен только закрывать сокет, если время истечения времени таймера в прошлом.
  • async_read() обработчик должен установить время истечения времени в будущем.

При таком подходе, если обработчик завершения async_read() работает до async_wait() , то либо async_wait() будет отменен, либо async_wait() обработчик завершения не закроет соединение, так как текущее время истечения будет в будущем. С другой стороны, если обработчик завершения async_wait() работает до async_read() , то либо async_read() будет отменен, либо async_read() обработчик завершения может обнаружить, что сокет закрыт.

. one of the most highly regarded and expertly designed C++ library projects in the world. — Herb Sutter and Andrei Alexandrescu, C++ Coding Standards

deadline_timer

Typedef for the typical usage of timer. Uses a UTC clock.

Types

The duration type.

The type of the executor associated with the object.

The time traits type.

Member Functions

Start an asynchronous wait on the timer.

Constructor to set a particular expiry time as an absolute time.

Constructor to set a particular expiry time relative to now.

Move-construct a basic_deadline_timer from another.

Cancel any asynchronous operations that are waiting on the timer.

Cancels one asynchronous operation that is waiting on the timer.

Get the timer’s expiry time as an absolute time.

Set the timer’s expiry time as an absolute time.

Get the timer’s expiry time relative to now.

Set the timer’s expiry time relative to now.

Get the executor associated with the object.

(Deprecated: Use get_executor().) Get the io_context associated with the object.

(Deprecated: Use get_executor().) Get the io_context associated with the object.

Move-assign a basic_deadline_timer from another.

Perform a blocking wait on the timer.

Destroys the timer.

The basic_deadline_timer class template provides the ability to perform a blocking or asynchronous wait for a timer to expire.

A deadline timer is always in one of two states: «expired» or «not expired». If the wait() or async_wait() function is called on an expired timer, the wait operation will complete immediately.

Most applications will use the deadline_timer typedef.

Thread Safety
Examples

Performing a blocking wait:

Performing an asynchronous wait:

Changing an active deadline_timer’s expiry time

Changing the expiry time of a timer while there are pending asynchronous waits causes those wait operations to be cancelled. To ensure that the action associated with the timer is performed only once, use something like this: used:

I expected the code below to print Hello, world! every 5 seconds, but what happens is that the program pauses for 5 seconds and then prints the message over and over with no subsequent pauses. What am I missing?

edit to add working code below. thanks guys.

3 Answers 3

You’re creating the deadline_timer as a local variable and then immediately exiting the function. This causes the timer to destruct and cancel itself, and calls your function with an error code which you ignore, causing the infinite loop.

Using a single timer object, stored in a member or global variable, should fix this.

If you look at the error code, you’re getting operation cancelled errors.

Понравилась статья? Поделиться с друзьями:
Vkontakte.INFO
Добавить комментарий

;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!: