Я пытаюсь понять порядок памяти, связанный с функциями инициации ASIO и обработчиками завершения, но я не могу найти никакой документации по этому вопросу. Поскольку конструктор потока синхронизируется с началом функции потока ([Thread.Thread.Constr]), это гарантирует, что оценки выражения в обработчике завершения (который запускается в одном из этих потоков), межпоточная трансляция происходит после вызова к инициирующей функции. Таким образом, все, что я делаю в основном потоке перед запуском потока (ов), гарантированно произойдет до того, как что -либо в обработчике завершения.
Однако, если io_context :: run потоки уже запущены, когда мы вызовываем функцию инициации, мы не можем полагаться на эту синхронизацию. Есть ли какая-то другая операция синхронизации, которая гарантирует, что оценки экспрессии в обработчиках завершения проводятся после вызова инициирующей функции?
Код: Выделить всё
#include
#include
#include
int main()
{
boost::asio::io_context io_context;
auto work = boost::asio::make_work_guard(io_context);
std::thread io_runner([&io_context]()
{
io_context.run();
});
int i{0};
boost::asio::steady_timer timer(io_context, std::chrono::milliseconds(500));
i++;
timer.async_wait([&](const boost::system::error_code&)
{
i++;
});
//i++; //Comment in to trigger tsan
std::this_thread::sleep_for(std::chrono::seconds(1));
io_context.stop();
io_runner.join();
}
Как вы можете видеть, я запускаю функцию io_context :: run перед вызовом функции инициации, чтобы намеренно избегать синхронизации, упомянутой выше. Почему нет? Что именно вызывает, что i ++ в основном потоке произойдет до того, как i ++ в обработчике завершения? (Обратите внимание, я знаю, что это раса данных, она преднамеренная и здесь, чтобы продемонстрировать, как дезинфицирующее средство потока предупреждает об этом, но не в исходном коде.) < /P>
Что конкретно вызывает синхронизацию в исходном коде? И это задокументировано где -нибудь?
Подробнее здесь:
https://stackoverflow.com/questions/797 ... n-handlers