Привет. Что-то я не совсем до конца понял как что за ливер в асио и как он функционирует. Наткнулся на такое и не понял зачем в аксептор отдают стрэнд. Чисто инуитивно - видимо альтернативная форма вместо той, когда стрэнд предается через async_…().
tcp::acceptor acceptor_;
net::io_context& ioc_;
...
acceptor_(net::make_strand(ioc))
В терминах асио, strand - executor. Разжуйте в целом механизм - как происходит вызов конечной функции-обработчика в асио и какую функцию в этом играет экзекъютер. Как бы понятно про проактор и все такое, поставили в очередь, задание запустилось на другом потоке (зашедшем в ран()), поток закончил, вызвали функтор обработчик события. Интересно именно роль в этом процессе executor’а, хочется понять принцип синхронизации через strand. Например, экзекъютер - контейнер асинхронных заданий с обработчиками, который выдает задание из своей очереди по запросу. Тут реализованы различные стратегии вроде strand (предыдущий не закончил, следущее задание strand не отдаст).
И еще не понял такое из асио доков
In the case of composed asynchronous operations, such as async_read() or async_read_until(), if a completion handler goes through a strand, then all intermediate handlers should also go through the same strand.
Что за промежуточные хендлеры? Под хендлером ведь понимаются обработчики, которые передал в read_async(), например, но видимо я что-то не понял. Или промежуточный хендлер - это само чтение из сокета?
PS: конструктор аксептора в доках видел, но сильно яснее не становится:
The I/O executor that the acceptor will use, by default, to dispatch handlers for any asynchronous operations performed on the acceptor.
PPS: нет бы в доках нарисовать достаточно подробную схему взаимодействия основных сущностей вместо тысячи слов, иначе идти в отладчик и штудировать backtrace, весело.