Comment voulez-vous mettre en œuvre un événement de base de la boucle?
Si vous avez travaillé avec les kits graphiques, vous savez qu'il ya un événement de la boucle principale de la boucle qui doit être exécutée après avoir tout fait, et qui permettra de garder l'application en vie et en réponse à différents événements. Par exemple, pour Qt, vous voulez faire cela dans main():
int main() {
QApplication app(argc, argv);
//init code
return app.exec();
}
Qui, dans ce cas, app.exec() est l'application principale de la boucle.
Le moyen le plus évident à mettre en œuvre ce genre de boucle serait:
void exec() {
while (1) {
process_events(); //create a thread for each new event (possibly?)
}
}
Mais cela limite le CPU à 100% et n'est pratiquement inutile. Maintenant, comment puis-je mettre en œuvre un tel événement boucle qui est sensible sans manger le CPU en tout?
Réponses sont appréciées en Python et/ou C++. Merci.
Note de bas de page: Pour l'amour de l'apprentissage, je vais mettre en place mes propres signaux/slots, et je voudrais les utiliser pour générer des événements personnalisés (par exemple,go_forward_event(steps)
). Mais si vous savez comment je peux utiliser le système manuellement des événements, je voudrais savoir en parler.
- Je crois que vous pouvez vous plonger dans le code source de Qt et de voir exactement ce qu'ils font dans exec(). Ce serait probablement vous donner quelques bons conseils.
Vous devez vous connecter pour publier un commentaire.
Je me demandais beaucoup sur la le même!
Une interface graphique boucle principale ressemble à ça, en pseudo-code:
Qu'est ce qu'un "Waitable"? Eh bien, c'est le système de charge. Sous UNIX, il est appelé un "descripteur de fichier" et "waitOnAll" est l' ::sélectionnez appel système. Le soi-disant
vector<Waitable>
est un::fd_set
sur UNIX, et "whatHappened" est en fait interrogé viaFD_ISSET
. La réelle waitable-les poignées sont acquises de diverses façons, par exemplem_xConnection
peuvent être prises à partir de ::XConnectionNumber(). X11 fournit également un haut-niveau, portable API pour cela -- ::XNextEvent() -- mais si vous les utilisez, vous ne serait pas en mesure d'attendre sur plusieurs sources d'événements simultanément.Comment fonctionne le blocage de travail? "waitOnAll" est un syscall qui raconte l'OS pour mettre votre processus sur une "liste de sommeil". Cela signifie que vous ne sont pas donnés à tout le temps CPU jusqu'à ce qu'un événement se produit sur l'un des waitables. Cela signifie que votre processus est ralenti, en consommant 0% de CPU. Lorsqu'un événement se produit, votre processus brièvement réagir et puis retour à l'état inactif. Les applications à interface graphique passent presque tous leur temps de marche au ralenti.
Ce qui arrive à tous les cycles de l'UC pendant que vous dormez? Dépend. Parfois, un autre processus a une utilisation pour eux. Si non, votre système d'exploitation occupé de la boucle de la CPU, ou le mettre en temporaire de faible puissance, mode, etc.
Il vous plaît demander pour plus de détails!
Python:
Vous pouvez regarder à la mise en œuvre de la Twisted réacteur qui est probablement la meilleure mise en œuvre pour une boucle en python. Les réacteurs Tordus sont des implémentations de l'interface et vous pouvez spécifier un réacteur de type court: sélectionner, epoll, kqueue (le tout basé sur une api en c à l'aide de ces appels système), il y a aussi des réacteurs basés sur l'intervalle QT et GTK boîtes à outils.
Une mise en œuvre simple serait d'utiliser select:
En général, je voudrais le faire avec une sorte de comptage de sémaphore:
Si vous ne voulez pas d'obtenir de bien compliqué, vous avez juste à ajouter un sleep() appel dans votre boucle while avec un infiniment petit du temps de sommeil. Qui sera la cause de votre message thread de traitement pour le rendement c'est le temps CPU pour les autres threads. Le CPU ne sera pas fixé à 100%, pas plus, mais c'est encore assez inutile.
Je voudrais utiliser un simple, la lumière-poids de messagerie bibliothèque appelée ZeroMQ (http://www.zeromq.org/). C'est une bibliothèque open source (LGPL). C'est une très petite bibliothèque; sur mon serveur, l'ensemble du projet compile en environ 60 secondes.
ZeroMQ sera extrêmement simplifier votre événement piloté par le code, ET c'est aussi la solution LA plus efficace en termes de performances. La communication entre les threads à l'aide de ZeroMQ est beaucoup plus rapide (en termes de vitesse) que l'utilisation de sémaphores ou local, les sockets UNIX. ZeroMQ aussi être un 100% solution portable, alors que toutes les autres solutions de lier votre code vers le bas pour un système d'exploitation spécifique.