Bienvenue, Invité. Merci de vous connecter ou de vous inscrire.
Avez-vous perdu votre e-mail d'activation ?

Auteur Sujet: Comment bien utiliser les mutex ?  (Lu 34992 fois)

0 Membres et 1 Invité sur ce sujet

Lolilolight

  • Hero Member
  • *****
  • Messages: 1232
    • Voir le profil
Re : Comment bien utiliser les mutex ?
« Réponse #90 le: Août 11, 2013, 07:27:46 pm »
Salut,
J'ai une question, peut on utiliser une variable de condition dans la méthode update de Qt ???

Quand j'assaye de le faire j'ai un plantage, il m'affiche std::system error, operation not permitted :

//Méthode appelée lors de la mise à jour de l'affichage. (Raffraichissement.)
void MyCanvas::onUpdate () {
    unique_lock<mutex> locker(g_lock_update_scene);
    g_signal.wait(locker, [&]() { return !parent->getSceneUpdater()->isGDone();});
 

Est ce normal ?

Laurent

  • Administrator
  • Hero Member
  • *****
  • Messages: 32504
    • Voir le profil
    • SFML's website
    • E-mail
Re : Comment bien utiliser les mutex ?
« Réponse #91 le: Août 11, 2013, 07:39:01 pm »
Citer
peut on utiliser une variable de condition dans la méthode update de Qt
Je ne vois pas pourquoi on ne pourrait pas. Au pire tu aurais pu essayer la même chose dans une autre fonction, pour t'en assurer.

Si tu as une exception, il ne devrait pas être compliqué de voir où elle a été lancée avec le debugger. Tu peux aussi consulter la doc pour voir dans quelles circonstances cette exception peut être lancée.
Laurent Gomila - SFML developer

Lolilolight

  • Hero Member
  • *****
  • Messages: 1232
    • Voir le profil
Re : Comment bien utiliser les mutex ?
« Réponse #92 le: Août 11, 2013, 08:35:43 pm »
Bah avec un autre bout de code sans passé par un QTimer qui rafraichi la vue toute les x millisecondes ça marche très bien.
QTimer utilise surement un QThread pour rafraichir la vue.
Peut être est parce que j'utilise une primitive de synchronisation non supportée par un QThread  dans l'exécution de ce QThread.

Je vais aller voir sur le forum de Qt, au pire, je virerai ce QTimer et j'utiliserai un std::thread pour appeler le repaint du widget, le débuguer me dis que le ça plante dans la méthode repaint de Qt, mais ne me donne pas beaucoup d'infos. :/

Voici ce que me dis le débuguer :
#0 649431BD     ??() (C:\MinGW\bin\libwinpthread-1.dll:??)
#1 0041CF06     QSFMLCanvas::paintEvent(this=0xbaadf00d) (D:\Projets-c++\Sorrok\GraphicEngine\qSFMLcanvas.cpp:118)
#2 01781C3B     ZN7QWidget5eventEP6QEvent() (C:\qt-everywhere-opensource-src-5.1.0\qtbase\lib\Qt5Widgets.dll:??)
#3 01630000     ?? () (??:??)
#4 0717D4F0     ?? () (??:??)
 
« Modifié: Août 11, 2013, 08:43:43 pm par Lolilolight »

Laurent

  • Administrator
  • Hero Member
  • *****
  • Messages: 32504
    • Voir le profil
    • SFML's website
    • E-mail
Re : Comment bien utiliser les mutex ?
« Réponse #93 le: Août 11, 2013, 09:10:34 pm »
Citer
QTimer utilise surement un QThread pour rafraichir la vue.
Non. Tout se passe dans le thread principal.

Citer
Peut être est parce que j'utilise une primitive de synchronisation non supportée par un QThread  dans l'exécution de ce QThread.
QThread n'a pas à "supporter" les primitives de synchronisation. Au final ton code tourne dans un thread de l'OS, quelque soit le wrapper qui l'a lancé.

Citer
le débuguer me dis que le ça plante dans la méthode repaint de Qt, mais ne me donne pas beaucoup d'infos. :/
Ton this est pourri. Ca se voit quand même assez bien là, non ??
QSFMLCanvas::paintEvent(this=0xbaadf00d)

Citer
Je vais aller voir sur le forum de Qt, au pire, je virerai ce QTimer et j'utiliserai un std::thread pour appeler le repaint du widget
Si tu t'entêtes à chercher les erreurs ailleurs que dans ton code, pour ma part j'en resterai là. Marre de perdre mon temps, il faut toujours 5 pages de posts pour que tu arrives à admettre que le bug venait bien de toi.
Laurent Gomila - SFML developer

cobra.one

  • Newbie
  • *
  • Messages: 26
    • Voir le profil
Re : Re : Comment bien utiliser les mutex ?
« Réponse #94 le: Août 12, 2013, 12:32:32 am »
Je vais aller voir sur le forum de Qt, au pire, je virerai ce QTimer et j'utiliserai un std::thread pour appeler le repaint du widget, le débuguer me dis que le ça plante dans la méthode repaint de Qt, mais ne me donne pas beaucoup d'infos. :/

QThread, std::thread, sf:Thread = idem. Juste des interfaces vers les threads OS. Et bon courage pour faire un repaint depuis un autre thread. Qt n'accepte pas que tu manipules un widget dans un autre thread que celui qui l'a créé si mes souvenirs sont bons (comme la plupart des bibliothèques d'IHM d'ailleurs). Si tu appelles n'importe quelle méthode depuis un thread, cette méthode s'exécute dans ce même thread.

Et puisque je vois que tu utilises Qt, une petite remarque sur la pertinence de blinder ton code de threads pour tirer partie des CPU multi-coeurs : regarde juste combien ton programme compte de threads sans même compter les tiens... sûrement plus que ton CPU n'a de coeurs...
« Modifié: Août 12, 2013, 12:39:11 am par cobra.one »

Lolilolight

  • Hero Member
  • *****
  • Messages: 1232
    • Voir le profil
Re : Comment bien utiliser les mutex ?
« Réponse #95 le: Août 12, 2013, 09:25:26 am »
Ok, ok.

Bon j'ai essayer avec un plus petit code et là ça marche.
J'ai déclaré les mutex et variables de condition en global et je n'ai plus d'exception, par contre notify_one ne débloque pas le wait du coup il ne sort pas de ma variable de condition :

unique_lock<mutex> locker(g_lock_update_component);
    g_signal.wait(locker, [&](){return parent->getSceneUpdater()->isGNotified();});
    cout<<"draw"<<endl;
 

void SceneUpdater::run () {


    while (running) {

        unique_lock<mutex> locker(g_lock_update_component);
        gNotified = false;

        //lock_guard<recursive_mutex> lock(rec_mutex);

        Vector2f centerView = canvas->getCenterView();
        canvas->getMap().gridMap->checkVisibleTiles(centerView);
        visibleTiles = canvas->getMap().gridMap->getVisibleTiles();
        //canvas->getMap().gridMap->checkCollisions(centerView);
        BoundingRectangle br = canvas->getBoundingRectangle();
        canvas->getLightManager().checkVisibleLights(br);
        visibleLights = canvas->getMap().gridMap->getVisibleLights();
        canvas->getLightManager().checkVisibleShadows();
        visibleShadows = canvas->getLightManager().getAllVisibleShadows();
        vector<Anim*> anims = canvas->getMap().gridMap->getAnims ();
        for (unsigned int i = 0; i < animations.size(); i++) {
            anims.push_back(animations[i]);
        }

        for (unsigned int i = 0; i < anims.size(); i++) {
            if (anims[i]->isRunning() && anims[i]->getElapsedTime().asMilliseconds() > anims[i]->getFrameRate()) {

                anims[i]->nextImage();

                Vec2f center = anims[i]->getCenter();
                if (canvas->getMap().gridMap->containsAnim(anims[i], center)) {
                    Tile *prev = anims[i]->getCurrentTile();
                    Tile *newTile = anims[i]->getCurrentTile();
                    Vec2f centerView (canvas->getCenterView().x, canvas->getCenterView().y);
                    canvas->getMap().gridMap->changeAnimTile(centerView, prev, newTile);
                }

                anims[i]->resetClock();

            }

        }
        gNotified = true;
        g_signal.notify_one();
        this_thread::sleep_for(chrono::milliseconds(100));
    }
}
 
Quand j'enlève le g_signal.wait là par contre ça marche bien et c'est plus rapide que les mutex. :)

Lolilolight

  • Hero Member
  • *****
  • Messages: 1232
    • Voir le profil
Re : Comment bien utiliser les mutex ?
« Réponse #96 le: Août 12, 2013, 10:14:25 am »
Bon quand je ne déclare plus le mutex en global, mais dans ma classe Frame, le g_signal.wait marche, par contre mon FPS baisse a 10.
Il se passe des choses bizarre dans ce monde.  :o

Laurent

  • Administrator
  • Hero Member
  • *****
  • Messages: 32504
    • Voir le profil
    • SFML's website
    • E-mail
Re : Comment bien utiliser les mutex ?
« Réponse #97 le: Août 12, 2013, 10:19:48 am »
Citer
Il se passe des choses bizarre dans ce monde.
Dans ton code ;)
Laurent Gomila - SFML developer

Lolilolight

  • Hero Member
  • *****
  • Messages: 1232
    • Voir le profil
Re : Comment bien utiliser les mutex ?
« Réponse #98 le: Août 12, 2013, 10:22:40 am »
Haaa j'ai trouvé, j'avais oublié d'enlever cette ligne-ci qui ralentissait tout.
this_thread::sleep_for(chrono::milliseconds(100));
 

L'exception se levait donc juste parce que j'avais déclaré le g_signal dans ma classe Frame (Celle qui contient le render component et le sceneupdater.), depuis que j'ai déclaré le g_signal en global plus d'exception.
Par contre le mutex j'ai du le déclaré dans la classe Frame et la passer à mon rendercomponent et à mon sceneudater sinon le notify_one ne marchait pas.
Je ne comprends pas très bien pourquoi, bref...

Maintenant j'ai une appli multi-threadée qui marche! (FPS de 60.) like a boss.  :D

Alors qu'est ce que tu dis de ce code ?
« Modifié: Août 12, 2013, 10:27:02 am par Lolilolight »

Laurent

  • Administrator
  • Hero Member
  • *****
  • Messages: 32504
    • Voir le profil
    • SFML's website
    • E-mail
Re : Comment bien utiliser les mutex ?
« Réponse #99 le: Août 12, 2013, 10:35:22 am »
Citer
Alors qu'est ce que tu dis de ce code ?
Pas grand chose. C'est ton code et il est bien fourni, j'ai pas vraiment pris le temps de l'analyser.

Citer
Maintenant j'ai une appli multi-threadée qui marche! (FPS de 60.) like a boss.
Moi à ta place je ne serais pas aussi content de moi-même. Je préfère largement avoir un code qui tourne mal en sachant exactement pourquoi, qu'avoir un code qui tourne bien en ayant laissé de côté plein de zones d'ombres. Je m'attends à te revoir bientôt sur le forum avec ce même code.
Laurent Gomila - SFML developer

cobra.one

  • Newbie
  • *
  • Messages: 26
    • Voir le profil
Re : Comment bien utiliser les mutex ?
« Réponse #100 le: Août 12, 2013, 11:20:09 am »
Et quelques incantations plus loin... http://fr.sfml-dev.org/forums/index.php?topic=12610.0

Lolilolight

  • Hero Member
  • *****
  • Messages: 1232
    • Voir le profil
Re : Comment bien utiliser les mutex ?
« Réponse #101 le: Août 12, 2013, 12:48:03 pm »
Bah il faudrait que je lise des books mais pas trop le temps ça va plus vite de midifier un peu de code que de lire un article de... 100 pages. (Oui bon j'exagère peut être.)

Sinon, si quelqu'un de plus expérimenté pourrait m'expliquer pourquoi le QTimer me lance une exception si je ne déclare pas ma variable de condition statique et que je dois déclarer le mutex comme étant non statique sinon, ça bloque ma méthode onUpdate(), se serait bien.

Pas trop le temps de chercher pouquoi. :/
« Modifié: Août 12, 2013, 12:49:36 pm par Lolilolight »

Laurent

  • Administrator
  • Hero Member
  • *****
  • Messages: 32504
    • Voir le profil
    • SFML's website
    • E-mail
Re : Comment bien utiliser les mutex ?
« Réponse #102 le: Août 12, 2013, 12:50:32 pm »
Citer
Sinon, si quelqu'un de plus expérimenté pourrait m'expliquer pourquoi le QTimer me lance une exception si je ne déclare pas ma variable de condition statique et que je dois déclarer le mutex comme étant non statique sinon, ça bloque ma méthode onUpdate(), se serait bien.
Si tu prenais le temps de mieux expliquer ton problème, avec des détails et un code complet minimal, ce serait bien. On n'est pas à ta place, on n'a pas une connaissance absolue de ton code, il faut nous aider si tu veux qu'on t'aider.
Laurent Gomila - SFML developer

Lolilolight

  • Hero Member
  • *****
  • Messages: 1232
    • Voir le profil
Re : Comment bien utiliser les mutex ?
« Réponse #103 le: Août 12, 2013, 01:17:06 pm »
Ok je posterai quelques codes, mais là, il faut que je fasse plusieurs codes minimal différent pour voir exacement là ou ça ne va pas parce que j'ai un code minimal avec juste une QMainWindow et un QSfmlCanvas, ça marche, puis dans mon code plus complexe ou j'ai tout dans un QStackedLayout qui est dans une QMainFrame, là, ça ne marche plus, bref, je suis un peu, perdu.
Je ferai des tests plus approfondis quand j'aurai le temps.
Mais comme ça prend beaucoup de temps je fais cela que si c'est nécessaire, c'est à dire, quand mon code ne tourne pas.
« Modifié: Août 12, 2013, 01:18:58 pm par Lolilolight »

Laurent

  • Administrator
  • Hero Member
  • *****
  • Messages: 32504
    • Voir le profil
    • SFML's website
    • E-mail
Re : Comment bien utiliser les mutex ?
« Réponse #104 le: Août 12, 2013, 01:23:35 pm »
Oui, mais il faut quand même le faire avant de nous demander de l'aide.
Laurent Gomila - SFML developer