Как использовать asio::strand в библиотеке, которая предоставляет как блокирующие, так и асинхронные функцииC++

Программы на C++. Форум разработчиков
Ответить
Anonymous
 Как использовать asio::strand в библиотеке, которая предоставляет как блокирующие, так и асинхронные функции

Сообщение Anonymous »

Я пытаюсь изучить asio, написав библиотеку, которая подключается к определенному устройству
через UDP-соединение.
Когда устройство включается, оно переходит в режим широковещания, в котором оно передает свою
личность в сеть. Таким образом, хост-компьютеру необходимо прослушивать udp-порт на наличие
пакетов, соответствующих формату устройства, и отслеживать устройства, которые
уже обнаружены, поскольку устройство будет продолжать широковещательную передачу даже после
соединение.
Я сделал несколько прототипов на Python, и асинхронный генератор
очень хорошо подошел для этого варианта использования. Но в asio естественным аналогом является

Код: Выделить всё

asio::ip::tcp::acceptor
.
Я ожидаю, что мой пользовательский акцептор будет запускаться из многопоточного
io_context, поскольку каждое устройство имеет высокую скорость передачи данных. Я думаю, это означает, что
мне нужно использовать цепь для акцептора, а также для каждого контроллера устройства, чтобы
упорядочивать операции. Итак, у меня есть два вопроса о том, как использовать цепочку
в отношении этого фрагмента кода:

Код: Выделить всё

template 
class Acceptor {
std::unordered_set accepted_connections;
asio::basic_datagram_socket receive_sock;

std::shared_ptr accept(asio::error_code& ec) {
std::array buffer;
typename asio::basic_datagram_socket::endpoint_type remote_endpoint;
receive_sock.receive_from(asio::buffer(buffer), remote_endpoint, {}, ec);
if (!ec) {
return {};
}
if (accepted_connections.contains(remote_endpoint)) {
return {};
}
if (auto ret = std::start_lifetime_as(buffer.data())->validate(); !ret) {
ec = ret.error();
return {};
}
accepted_connections.emplace(remote_endpoint.remote_endpoint());
return MakeDevice(remote_endpoint, buffer);
}
};
#1) Как мне изменить мою блокирующую функцию принятия, чтобы она выполнялась внутри цепочки, чтобы
чтобы любой доступ к набору Accept_connections сериализовался правильно? Из
что могу сказать, все варианты исполнения на пряди(

Код: Выделить всё

defer,
dispatch
, выполнить, post) разрешено помещать функцию в очередь
нитей и выполнять позже. Это делает проверку error_code невозможной
потому что, если исполнитель запустит содержимое этой функции позже, когда Accept
вернет немедленно, переменная ec еще не будет установлена. Из-за косвенности,
которая поддерживает различные собственные сокеты, посмотрите исходный код, чтобы узнать, как

Код: Выделить всё

socket Acceptor::accept(endpoint& peer_endpoint, error_code& ec)
работает
не очень информативно.
#2) При реализации async_accept я думаю, мне нужно использовать async_initiate, чтобы
сделать это совместим с другими токенами завершения. Но как включить в него
цепочку, чтобы набор Accepted_connections сохранялся в порядке? Ожидаю ли я
цепи внутри моей сопрограммы или мне нужно что-то сделать с моим
async_initiate, чтобы сопрограмма выполнялась в цепочке.

Подробнее здесь: https://stackoverflow.com/questions/777 ... and-asynch
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C++»