est-il possible d'effectuer une attente asynchrone (lecture: non bloquante) sur une variable conditionnelle à Boost :: Asio? S'il n'est pas directement soutenu des indications sur la mise en œuvre, elle serait appréciée. P>
Je pourrais mettre en œuvre une minuterie et tirer un réveil, même tous les quelques ms, mais c'est une approche très inférieure, j'ai du mal à croire que la synchronisation variable de condition n'est pas mise en œuvre / documentée. p>
3 Réponses :
Si je comprends bien l'intention correctement, vous souhaitez lancer un gestionnaire d'événements, lorsque la variable de condition est signalée, dans le contexte de la piscine de fil ASIO? Je pense qu'il serait suffisant d'attendre sur la variable de condition au début du gestionnaire, et IO_Service :: Post () lui-même dans la piscine à la fin, quelque chose de ce genre:
#include <iostream> #include <boost/asio.hpp> #include <boost/thread.hpp> boost::asio::io_service io; boost::mutex mx; boost::condition_variable cv; void handler() { boost::unique_lock<boost::mutex> lk(mx); cv.wait(lk); std::cout << "handler awakened\n"; io.post(handler); } void buzzer() { for(;;) { boost::this_thread::sleep(boost::posix_time::seconds(1)); boost::lock_guard<boost::mutex> lk(mx); cv.notify_all(); } } int main() { io.post(handler); boost::thread bt(buzzer); io.run(); }
Mais le fil qui attend sera bloqué, n'est-il pas un moyen de ne pas bloquer un fil, mais d'enregistrer un gestionnaire d'achèvement à la place? Je suis actuellement consorant un mécanisme alternatif ici Stackoverflow.com/Questtions/6776779/...
@Hassan SYED: une variable de condition est un concept qui implique un fil bloqué. Peut-être que vous recherchez des signaux asynchronisés à la place? Boost.Asio Just Ajout de la prise en charge des gestionnaires de signaux dans 1.47.0: boost.org/doc/libs/1_47_0/doc/html/boost_asio/history.html
Pour autant que je sache, ce sont des signaux émis par le système d'exploitation. Il est montré que vous pouvez vous inscrire à ces signaux, mais c'est le système d'exploitation qui les émettra.
Votre réponse est correcte, je fonctionnais sous l'hypothèse selon laquelle io_service :: exécuté () code> est un appel de blocage de la callee et que ASIO s'occupe de la synchronisation en quelque sorte. Je suis content que cette hypothèse n'était pas vraie.
Le lien io_service :: post code> dans la réponse est cassé. Était
io_service :: post code> supprimé? Il n'apparaît pas dans la section de référence actuelle de l'ASIO DOC.
Je peux suggérer une solution basée sur Boost :: Asio :: Date LineL_Timer qui fonctionne bien pour moi. C'est un peu d'événement asynchronisé à Boost :: Asio Environment. Une chose très importante est que le «gestionnaire» doit être sérialisé via le même «Strand_» comme «Annuler», car utiliser «Boost :: Asio :: DateLline_Timer» de plusieurs threads n'est pas un fil de sécurité.
class async_event { public: async_event( boost::asio::io_service& io_service, boost::asio::strand<boost::asio::io_context::executor_type>& strand) : strand_(strand) , deadline_timer_(io_service, boost::posix_time::ptime(boost::posix_time::pos_infin)) {} // 'handler' must be serialised through the same 'strand_' as 'cancel' or 'cancel_one' // because using 'boost::asio::deadline_timer' from multiple threads is not thread safe template<class WaitHandler> void async_wait(WaitHandler&& handler) { deadline_timer_.async_wait(handler); } void async_notify_one() { boost::asio::post(strand_, boost::bind(&async_event::async_notify_one_serialized, this)); } void async_notify_all() { boost::asio::post(strand_, boost::bind(&async_event::async_notify_all_serialized, this)); } private: void async_notify_one_serialized() { deadline_timer_.cancel_one(); } void async_notify_all_serialized() { deadline_timer_.cancel(); } boost::asio::strand<boost::asio::io_context::executor_type>& strand_; boost::asio::deadline_timer deadline_timer_; };
Malheureusement, Boost Asio n'a pas de Dans la plupart des cas, vous n'en aurez pas non plus besoin. La programmation de la voie ASIO signifie généralement que vous utilisez des brins, non des mautexes ou des variables de condition, pour protéger les ressources partagées. Sauf pour des cas rares, qui se concentrent généralement sur une commande de construction ou de destruction correcte au démarrage et de sortie, vous n'aurez pas besoin de mautexes ou de variables de condition du tout. P> Lors de la modification d'une ressource partagée, le filetage classique, partiellement synchrone La façon est la suivante: p> La voie d'ASIO entièrement asynchrone est cependant: p> Voici un exemple de classe Bien sûr, l'exemple n'est pas Achevée; async_wait_for_condvar () code> méthode.
quelque_shared_resource code>, qui reçoit une chaîne
état code> et déclenche un autre traitement supplémentaire en fonction de l'état reçu. Veuillez noter que tous les traitements de la méthode privée
quelque_shared_resource :: Receive_State () code> est entièrement sécurisé, car le brin sérialisement tous les appels. P>
Quelqu'un_other_Resource Code> a besoin d'un similiaire
send_code_red () code> méthode comme
one_shared_ressource :: send_state () code>. p>
#include <boost/asio>
#include <memory>
using asio_context = boost::asio::io_context;
using asio_executor_type = asio_context::executor_type;
using asio_strand = boost::asio::strand<asio_executor_type>;
class some_other_resource;
class some_shared_resource : public std::enable_shared_from_this<some_shared_resource> {
asio_strand strand;
std::shared_ptr<some_other_resource> other;
std::string state;
void receive_state(std::string&& new_state) {
std::string oldstate = std::exchange(state, new_state);
if(state == "red" && oldstate != "red") {
// state transition to "red":
other.send_code_red(true);
} else if(state != "red" && oldstate == "red") {
// state transition from "red":
other.send_code_red(false);
}
}
public:
some_shared_resource(asio_context& ctx, const std::shared_ptr<some_other_resource>& other)
: strand(ctx.get_executor()), other(other) {}
void send_state(std::string&& new_state) {
boost::asio::post(strand, [me = weak_from_this(), new_state = std::move(new_state)]() mutable {
if(auto self = me.lock(); self) {
self->receive_state(std::move(new_state));
}
});
}
};
Qu'est-ce que tu veux faire??? - est peut-être la dernière version de async_read_until A> Qu'est-ce que vous cherchez? L'attente non bloquante est normale une tâche pour Boost thread a > ... Stimuler le fil en combinaison avec Boost Asio devrait fonctionner ...
J'ai une autre implémentation à l'esprit, je l'ai décrite dans une autre question ici. Stackoverflow .Com / Questions / 6776779 / ... Cela pourrait vous donner plus de perspicacité à ce que je veux faire.