Annuler le minuteur Boost ASIO Deadline Timer en toute sécurité
Le code fourni est destiné à annuler un boost::asio::basic_waitable_timer en toute sécurité dans un fil de discussion séparé . Cependant, il semble que l'annulation ne fonctionne pas comme prévu en raison d'un problème sous-jacent.
Comprendre le problème :
Le problème vient du fait que le code fourni tente d'annuler le minuteur à l'aide de la fonction post, qui ajoute l'opération d'annulation à la file d'attente des événements du io_service du minuteur. Cette approche est problématique car si le minuteur a déjà expiré avant l'exécution de l'opération d'annulation, l'opération d'annulation sera ignorée, laissant effectivement le minuteur dans un état actif.
Résoudre le problème :
Pour résoudre ce problème, nous devons concevoir un moyen robuste d'annuler la minuterie quel que soit son état actuel. Une approche efficace consiste à introduire une valeur sentinelle pour le moment d’expiration du temporisateur qui signifie un état invalide. En définissant l'expiration du minuteur sur cette valeur sentinelle pendant le processus d'annulation, nous pouvons garantir que même si le minuteur a expiré avant l'annulation, il sera placé dans un état invalide, empêchant ainsi toute autre opération asynchrone.
Code modifié :
Implémenter l'approche de valeur sentinelle :
<code class="cpp">timer.get_io_service().post([](){ std::cerr << "tid: " << std::this_thread::get_id() << ", cancelling in post\n"; // Cancel: timer.expires_at(Timer::clock_type::time_point::min()); });</code>
Gestion du gestionnaire d'achèvement :
Dans le gestionnaire d'achèvement , vérifiez la valeur sentinelle pour détecter l'arrêt :
<code class="cpp">void handle_timeout(const boost::system::error_code& ec) { if (!ec) { started = true; if (timer.expires_at() != Timer::time_point::min()) { timer.expires_from_now(std::chrono::milliseconds(10)); timer.async_wait(&handle_timeout); } else { std::cerr << "handle_timeout: detected shutdown\n"; } } else if (ec != boost::asio::error::operation_aborted) { std::cerr << "tid: " << std::this_thread::get_id() << ", handle_timeout error " << ec.message() << "\n"; } }</code>
Avec l'approche de la valeur sentinelle, vous pouvez désormais annuler de manière fiable la minuterie même si elle a déjà expiré.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!