#1 Le 21/04/2014, à 15:38
- Lolichou
Gestion d'évènement multi-thread et freeze sous ubuntu.
Alors je tiens à préciser que ça tourne parfaitement sous windows. (Mais ça freeze sous ubuntu)
J'ai un système qui lie des évènements souris et clavier à des commandes.
Et j'exécute ses commandes dans un thread à part pour n'exécuter qu'une seule commande à la fois. (et ne pas attendre après tout les événements généré avec la fonction pollEvent de sfml dans une boucle while avant de mettre à jour le rendu)
Comme librairie graphique j'utilise SFML donc et comme language de programmation le c++ avec le nouveau standard c++11.
Lorsqu'un événement clavier ou souris est généré l'application l'ajoute dans une pile d'événement et le thread courant vérifie si l'événement correspond à une commande définie par le développeur :
void pushEvent(sf::Event event) {
ActionMap::pushEvent(event);
if (isOneTriggered()) {
one_triggered = true;
g_signal.notify_one();
g_notified = false;
std::unique_lock<std::mutex> locker(g_lock_listen);
g_signal.wait(locker, [&](){return g_notified;});
}
}
Si oui alors, j'endors le thread courant et j'exécute la commande dans un autre thread et je réveille le thread courant quand la commande a été exécutée :
void run () {
std::map<std::string, std::pair<std::vector<FastDelegate<bool>*>, std::vector<FastDelegate<void>*>>>::iterator it;
std::map<std::string, ActionMap*>::iterator it2;
while (running) {
std::unique_lock<std::mutex> locker(g_lock_listen);
g_signal.wait(locker, [&](){return one_triggered || !running;});
for (it = signals.begin(); it != signals.end(); it++) {
std::vector<FastDelegate<bool>*> signs = it->second.first;
for (unsigned int i = 0; i < signs.size(); i++) {
if ((*signs[i])()) {
std::vector<FastDelegate<void>*> slots = it->second.second;
for (unsigned int j = 0; j < slots.size(); j++) {
(*slots[j])();
}
}
}
}
for (it2 = actions.begin(); it2 != actions.end(); it2++) {
if (it2->second->isTriggered())
(*it2->second)();
}
ActionMap::clear();
locker.unlock();
g_notified = true;
g_signal.notify_one();
one_triggered = false;
}
}
Cependant, parfois, le thread courant ne se réveille pas et c'est assez lent, par exemple lorsque j'exécute une commande pendant qu'une touche est enfoncé et qu'après je relâche la touche, la commande ne s'arrête pas tout de suite.
Dernière modification par Lolichou (Le 21/04/2014, à 15:38)
Hors ligne
#2 Le 21/04/2014, à 16:49
- Lolichou
Re : Gestion d'évènement multi-thread et freeze sous ubuntu.
Ha, j'ai trouvé, il fallait déverouillé le mutex manuellement en fait.
void run() {
std::map<std::string, std::pair<std::vector<FastDelegate<bool>*>, std::vector<FastDelegate<void>*>>>::iterator it;
std::map<std::string, ActionMap*>::iterator it2;
while (running) {
std::unique_lock<std::mutex> locker(g_lock_listen);
g_signal.wait(locker, [&](){return one_triggered || !running;});
for (it2 = actions.begin(); it2 != actions.end(); it2++) {
if (it2->second->isTriggered())
(*it2->second)();
}
for (it = signals.begin(); it != signals.end(); it++) {
std::vector<FastDelegate<bool>*> signs = it->second.first;
for (unsigned int i = 0; i < signs.size(); i++) {
if ((*signs[i])()) {
std::vector<FastDelegate<void>*> slots = it->second.second;
for (unsigned int j = 0; j < slots.size(); j++) {
(*slots[j])();
}
}
}
}
g_notified = true;
one_triggered = false;
g_signal.notify_one();
locker.unlock();
}
}
void pushEvent(sf::Event event) {
ActionMap::pushEvent(event);
if (isOneTriggered()) {
one_triggered = true;
g_signal.notify_one();
g_notified = false;
std::unique_lock<std::mutex> locker(g_lock_listen);
g_signal.wait(locker, [&](){return g_notified;});
locker.unlock();
}
}
Voilà tout les bugs de ma petites librairies sont réglés et ça fonctionne sous linux je ferai une présentation du projets après et je le partagerai ici.
Ensuite je rajouterai un moteur de particule et quelque fonctionnalités pour la "full 3D" mais avant j'ai encore quelque petites choses à faire comme par exemple importer les fonctions pour le mode "shared".
Hors ligne