У меня есть программа, которая использует io_service и несколько потоков.
Она создает некоторое количество объектов сокетов.Каждый из этих объектов имеет цепь для синхронизации.Все вызовы async_read (), async_write () и подобных функций проходят через strand_.wrap (boost :: bind (...)).Каждый объект также имеет переменную int interlock_, которая инициализируется равной 0.
Внутри одной из этих функций (обратный вызов при получении данных) я делаю следующее:
Class::startRead(...)
{
...
boost::asio::async_read(socket_, boost::asio::buffer(ptr, 16384), boost::asio::transfer_at_least(1),
strand_.wrap(boost::bind(&EagerConnection::on_read, this, placeholders::error, placeholders::bytes_transferred)));
}
Class::on_read(...)
{
...
startRead();
assert(0 == __sync_fetch_and_add(&interlock_, 1));
onData_();
assert(1 == __sync_fetch_and_add(&interlock_, -1));
}
, посколькувсе синхронизируется через нить, что первое утверждение никогда не должно срабатывать.Тем не менее, это действительно огонь!Когда я проверяю значение в GDB, конечное значение interlock_ равно 2, что означает, что два отдельных вызова on_read () активны одновременно.
Означает ли это, что boost :: asio :: strandсломано?(Я уже проверил, что у меня нет повторного входа в функцию завершения - обработчик сигнала onData_ не вызывает повторно on_data ()).
Может ли "ранний" startRead как-то вызватьнемедленный повторный въезд?(Кажется, что и семантика async_x, и strand указывают на то, что это невозможно)
Если вы действительно, действительно хотите увидеть полный контекст класса, он доступен в виде сущности: https://gist.github.com/979212