Forum de la communauté SFML

Aide => Système => Discussion démarrée par: Lolilolight le Juillet 24, 2013, 01:05:00 pm

Titre: Comment bien utiliser les mutex ?
Posté par: Lolilolight le Juillet 24, 2013, 01:05:00 pm
Salut,

il y a un crash avec les sf::thread lorsque l'on récupère des variables dans le constructeur d'une classe qui instancie un sf::thread mais le problème ne survient qu'avec des méthodes statique qui renvoie une variable qui doit être partagée entre plusieurs thread.

SrkChannel::SrkChannel(SrkServer &server, string name) : server(server), name (name), thread (&SrkChannel::run, this)
{
    this->map = World::getMap("Map test");
    ...
}
 

Ca plante dans la fonction exécutée par mon thread, le débugueur ne me donne pas plus d'infos que ça, il me dis juste que ça plante lorsque le sf::thread exécute la fonction, lorque je veux utiliser la variable, ça plante dans la fonction entryPoint du fichier ThreadImpl.
#0 00436578 CellMap::getCenter(this=0xabababab) (D:\Projets-c++\SorrokSrv\world\mapCell.cpp:91)
#1 00434A8C GridMap::getPath(this=0x2f700e0, startPos=..., finalPos=...) (D:\Projets-c++\SorrokSrv\world\gridMap.cpp:425)
#2 00422FED SrkChannel::run(this=0x3014c28) (D:\Projets-c++\SorrokSrv\NetworkEngine\srkchannel.cpp:77)
#3 004CE8CD sf::priv::ThreadMemberFunc<SrkChannel>::run(this=0x2f7f220) (C:/SFML-2.0/include/SFML/System/Thread.inl:58)
#4 004A0297 sf::priv::ThreadImpl::entryPoint () (??:??)
#5 75861287 msvcrt!_itow_s() (C:\Windows\syswow64\msvcrt.dll:??)
#6 75861328 msvcrt!_endthreadex() (C:\Windows\syswow64\msvcrt.dll:??)
#7 749633AA KERNEL32!BaseCleanupAppcompatCacheSupport() (C:\Windows\syswow64\kernel32.dll:??)
#8 06EBFFD4 ?? () (??:??)
#9 77189EF2 ntdll!RtlpNtSetValueKey() (C:\Windows\system32\ntdll.dll:??)
#10 00DE70D0 ?? () (??:??)
#11 77189EC5 ntdll!RtlpNtSetValueKey() (C:\Windows\system32\ntdll.dll:??)
#12 758612E5 msvcrt!_endthreadex() (C:\Windows\syswow64\msvcrt.dll:??)
#13 ?? ?? () (??:??)

Y'a moyen de contourner le bug en récupérant l'objet dans une autre fonction que celle qui instancie le thread.

Bref faudrait que je poste ça dans les rapports de bugs avec un code tout bête qui reproduit le bug, peut être que certains pourront le corriger, moi, je pencherai plutôt pour une mauvaise initialisation de variables statiques partagées entre plusieurs threads.
PS : je pense que j'avais déjà eu ce bug plus tôt.
PS 2 : je voulais même passé au c++11 à cause de ça mais bon j'arrive pas à le faire marcher.
Titre: Re : Bug avec les threads.
Posté par: Laurent le Juillet 24, 2013, 01:18:59 pm
Il faut vraiment arrêter avec les conclusions hâtives. Là il y a 99.99% de chances pour que ce soit ton code qui est foireux, pas sf::Thread. Sûrement une mauvaise gestion de variables partagées entre threads.

Poste un code complet minimal qui reproduit le problème, ou, si c'est trop compliqué, au moins tous les morceaux de code qui sont pertinents.
Titre: Re : Bug avec les threads.
Posté par: Lolilolight le Juillet 24, 2013, 04:39:48 pm
Bon avec un code complet minimal je n'ai pas ce crash..., mais ça me le faisais que en mode débug, ce qui m'empêchais de pouvoir débuguer le reste du code...
Bref surement une erreur quelque part..., ici ça va vu que j'ai réussi à contourner le problème en mettant ça dans une méthode start plutôt que dans le constructeur.
Titre: Re : Bug avec les threads.
Posté par: Lolilolight le Juillet 25, 2013, 08:49:51 am
Bon c'est un problème d'accès concurrant ça c'est sûr mais même en mettant des mutex ça ne semble pas fonctionner. :/

J'ai déclaré le mutex dans un fichier .h (qui contient tout ce qui est variable globale) mais je suis obligé de le déclarer en static sinon j'ai des problèmes de multiple definition of, je ne peux pas le déclarer en dehors du main sinon je n'ai pas accès au mutex dans les autres fichiers.
J'ai aussi essayé de déclarer le mutex dans le main et le passer à toutes mes classes (chose trop lourde à faire.) mais ça ne résoud pas le problème. :/

Quand je fais un mutex.lock et mutex.unlock dans mes deux fonctions appelé par mes 2 threads, j'ai toujours un problème d'accès concurrant.
Titre: Re : Bug avec les threads.
Posté par: Lolilolight le Juillet 25, 2013, 08:59:43 am
Bon bah au final, en faisant plusieurs tests, j'ai trouvé d'où vient le bug.

Quand j'initialise une variable statique, avec une méthode statique dans le .cpp qui initialise d'autres variables, les mutex ne marchent pas pour ces autres variables.

J'espère que j'aurai été assez clair, c'est assez difficile de faire un code minimal qui reproduit le problème car je devrai m'arrangerai pour faire des accès concurrents...
Titre: Re : Bug avec les threads.
Posté par: Laurent le Juillet 25, 2013, 09:06:30 am
Citer
Les mutex ne fonctionnent pas pour les variables qui sont initialisée, non pas avec un constructeur, mais avec une méthode statique.
Là comme ça, ça ne veut pas dire grand chose. Peux-tu développer ?
Titre: Re : Bug avec les threads.
Posté par: Lolilolight le Juillet 25, 2013, 09:18:48 am
Ok alors je vais essayer de détailler ça avec un code. (Pas facile à expliquer. :/ )

J'ai une classe Bidule qui contient une méthode statique qui initialise une variable statique Truc
Voici le .h :
class Bidule {
private :
       static Truc& getTruc() {
                Truc *t = new Truc();
                return *t;
       }
       static Truc &truc;
};
 
Et le .cpp
Truc& Bidule::truc = getTruc();
 

Le mutex ne marche pas pour toutes les variables de la classe Truc.

Par contre si j'initialise les variables de la classe Truc plus tard, c'est à dire, dans une autre méthode que le constructeur de la classse truc, là, les mutex marchent.

Alors voici ma question : est ce normal ?
Titre: Re : Bug avec les threads.
Posté par: Laurent le Juillet 25, 2013, 09:26:38 am
Y a pas de mutex dans ton code.

Et "un mutex ne marche pas pour une variable" ça ne veut rien dire. Un mutex n'est pas lié à une variable, tu appelles juste des lock et des unlock dans ton code.

Donc, j'ai toujours rien compris. Et vu ta description du problème, je ne suis pas sûr que tu aies tout compris toi non plus.
Titre: Re : Bug avec les threads. (Les mutex ne marchent pas dans un certain cas précis.)
Posté par: Lolilolight le Juillet 25, 2013, 09:32:34 am
Ha moi si j'ai compris vu que je suis arrivé à contourner le bug.

Dans mon exemple plus haut, si j'ai un thread qui utilise une variable de la classe truc et que je fais un mutex.lock dans la fonction appelé par mon thread, les autres treads ont toujours accès à cette variable.

Mais j'ai corrigé le problème en initialisant les variables de la classe Truc plus tard c'est à dire dans une autre méthode que le constructeur de la classe Truc.

PS : ce que je n'ai pas compris c'est pourquoi mes autres threads ont accès aux variables de ma classe Truc dans mon exemple plus haut même quand je fais un mutex.lock dans la fonction appelée par mon thread.

PS 2 : si tu veux que je rajoute une classe Thread et un mutex dans mon code là peux être que tu pourras mieux comprendre.
Titre: Re : Bug avec les threads. (Les mutex ne marchent pas dans un certain cas précis.)
Posté par: Laurent le Juillet 25, 2013, 09:42:12 am
Citer
Ha moi si j'ai compris vu que je suis arrivé à contourner le bug.
Contourner un bug et comprendre un bug sont deux choses complètement différentes ;)

Citer
Dans mon exemple plus haut, si j'ai un thread qui utilise une variable de la classe truc et que je fais un mutex.lock dans la fonction appelé par mon thread, les autres treads ont toujours accès à cette variable.
Oui, ça c'est normal.
Mais tu veux dire que les autres threads verrouillent aussi le mutex, et que le verrouillage ne bloque pas même si ton autre thread l'a déjà verrouillé ?

Citer
PS 2 : si tu veux que je rajoute une classe Thread et un mutex dans mon code là peux être que tu pourras mieux comprendre.
Oui, j'aimerais bien voir le truc au complet, parce que là sinon on ne va pas s'en sortir.
Titre: Re : Bug avec les threads. (Les mutex ne marchent pas dans un certain cas précis.)
Posté par: Lolilolight le Juillet 25, 2013, 10:04:36 am
Ok voici le code complet :
Le fichier .h de la classe Bidule :
class Bidule {
private :
       static Truc& getTruc() {
                Truc *t = new Truc(5);
                return *t;
       }
       static int& getIVar ();
       static Truc &truc;
};
 
Le fichier .cpp de la classe Bidule :
Truc& Bidule::truc = getTruc();
int& Bidule::getIVar () {
       return truc.getIVar();
}
 
Le fichier.h de la classe truc :
class Truc {
private:
         int m_iVar;
public:
        Truc (int iVar);
        int& getIVar();
};
 
Le fichier .cpp de la classe Truc :
Truc::Truc(int iVar) : m_iVar(iVar) {
}
int& Truc::getTruc() {
       return m_iVar;
}
 

Et le main :
Mutex mutex;
void threadFunc () {
       //Problème : le mutex.lock ne marche pas, les autres thread ont accès à la variable iVar!
       mutex.lock();
       int& iVar = Bidule::getIVar();
       mutex.unlock();
}
void main () {
       Thread thread(&threadFunc);
       thread.launch();
}
 

Voilà j'ai mis le code complet et le problème que j'ai en commentaire.

PS : je fais aussi des mutex.lock et unlock dans toutes les fonctions appelées par mes autres thread mais ça ne résouds pas le problème.

PS 2 : je ne sais pas vraiment si le soucis vient de la SFML car j'ai lu sur un autre forum que l'on ne pouvait pas faire ce genre de chose avec le c++98 (impossibilité donc de faire des singletons thread-safe.), mais que le problème serais réglé avec le c++11. (Que j'aimerais bien essayer d'ailleurs mais je n'ai pas encore trouver une version de mingw avec support du c++11 en 32 bits pour tester ça.)
Ma version de mingw en 32 bits possède juste les include et j'ai plein de undefined reference to ... hors que mingw64 possède tout et là je n'ai pas de problèmes.
Titre: Re : Bug avec les threads. (Les mutex ne marchent pas dans un certain cas précis.)
Posté par: Hiura le Juillet 25, 2013, 10:33:33 am
Sans vouloir vexer, tu as meilleur temps d'apprendre un peu plus en détail la concurrence avant de te lancer à l'aveugle dedans.. sinon tu vas finir avec des designs vraiment bancales et ingéreables (comme ici).


A noter que le code que tu nous montres ne peut pas bugger: il n'y a qu'un thread actif donc pas de concurrence.
Titre: Re : Bug avec les threads. (Les mutex ne marchent pas dans un certain cas précis.)
Posté par: Laurent le Juillet 25, 2013, 10:53:53 am
Citer
je ne sais pas vraiment si le soucis vient de la SFML
Moi je sais que non. Tu devrais être un peu plus humble concernant ton propre code. A chaque fois tu viens en criant au bug dans SFML, mais en réalité il y a toujours plein de bourdes dans ton code. T'as pas encore vraiment le niveau d'un expert.

Ensuite je seconde Hiura : ton code ne montre qu'un thread, ça ne nous avance toujours pas à grand chose. Si tu as un problème d'accès concurrent, montre nous cet accès concurrent.

Et enfin concernant les compilos gcc 32 bits, normalement n'importe lequel en version au moins 4.7 supporte C++11 sans problème. Il faut parfois passer explicitement le flag std=c++11 (ou équivalent), mais sinon ça devrait marcher tel quel.
Titre: Re : Bug avec les threads. (Les mutex ne marchent pas dans un certain cas précis.)
Posté par: Lolilolight le Juillet 25, 2013, 12:28:34 pm
Ce code ne crash pas en effet vu qu'il n'y a qu'un seul thread qui utilise la variable mais je pensais que ça serait assez clair pour la compréhension de mon problème, mais je peux te dire que avec un plus gros code, c'est à dire, avec plusieurs threads et là ou il y a plus de chance d'avoir des accès concurrents, ça bug, je ne peux malheureusement donc pas te montrer avec un plus gros code.

Je ne suis pas rentré en détail dans la programmation multi-thread et la gestion des accès concurrents lors de mes études donc en effet, je ne suis surement pas un expert là dedans.

Mais bon là pour moi c'est clair, désolé.

Bref j'ai résolu le problème en initialisant la variable m_ivar dans une méthode que j'appelle après et non plus dans le constructeur de la classe truc, là, plus de problème d'accès concurrent et je ne broncherai plus ainsi. ^^

Titre: Re : Re : Bug avec les threads. (Les mutex ne marchent pas dans un certain cas précis.)
Posté par: Hiura le Juillet 25, 2013, 12:37:59 pm
Bref j'ai résolu le problème en initialisant la variable m_ivar dans une méthode que j'appelle après et non plus dans le constructeur de la classe truc, là, plus de problème d'accès concurrent et je ne broncherai plus ainsi. ^^

Aïe.

Je me permets juste de me citer:

Citer
sinon tu vas finir avec des designs vraiment bancales et ingéreables (comme ici).

Titre: Re : Bug avec les threads. (Les mutex ne marchent pas dans un certain cas précis.)
Posté par: Lolilolight le Juillet 25, 2013, 01:51:10 pm
Le design pourtant que j'utilise est exactement le même que celui de la plupart des frameworks  qui permettent de créer des jeux c'est à dire :

-Le "network" : contient tous les objets gérant le réseau.
-Le "world" : contient tous les objets du monde et la physique.
-Et le dernier gros module qui comprends tout ce qui gère l'affichage et les évènement.

Les objets des différents modules doivent toujours faire appels aux modules pour pouvoir communiquer avec des objets d'autres modules, car, les modules gèrent des objets en interne et ceux-ci ne doivent pas être accessible directement sans devoir passer par ces modules.

Bref ces gros modules contiennent tous des systèmes qui ne font que de stocker des informations et remettre à jour les objets. (Certains système utilisent des threads.)
Le but est de limiter un maximum les accès concurrents. (Le thread ajoute l'information dans une structure tandit que l'autre thread vérifie si il a reçus une information et ensuite met à jour si il y a lieu.)
Mais bon je ne peux pas toujours faire comme cela, car, parfois par exemple, les informations sont destinées au serveur ou à un canal, et ses canaux doivent tourner en parallèle avec le serveur, donc là, il peut y avoir des accès concurrents, il y a aussi des accès concurrent sur les sockets de la SFML, là je n'ai pas le choix vu que les sockets de l'API réseau apparemment ne sont pas thread safe. (Je pourrai modifier le code de la SFML pour que ce soit le cas mais j'ai préféré modifier mon code pour limiter les appels à lock et unlock trop nombreux quand j'utilise plusieurs sockets différent qui reçoivent des données à chaque tour de boucle ce qui est mon cas.)
Donc bon je pense pas que le design pose vraiment problème, d'ailleurs, au niveau exécution ça a toujours bien tourné à part se petit pépin que j'ai cité plus haut.

J'ai réglé le problème et ça retourne correctement, je vais pouvori entamer les quêtes, les sors avec système de shader, particule et tout le gameplay pour enfin finir ce petit projet SFML. (Avec à la fin, les sons, que je n'ai pas encore pu tester, là aussi il y a pas mal de thread à ce qu'il parait ça va encore être la joie. ^^)

Bref je vais m'arrêter là, je ne voudrai pas rentrer dans des débats, qui n'ont aucun sens.
Titre: Re : Bug avec les threads. (Les mutex ne marchent pas dans un certain cas précis.)
Posté par: Lolilolight le Juillet 30, 2013, 09:33:44 pm
Bon j'ai le même problème avec les thread du c++11, je suppose donc que pour que les mutex lock bien les variable, il faut initialiser les variables partagé entre plusieurs thread après avoir initialisé le thread. (Ou alors, pas avant l'appel d'un constructeur, c'est à dire, pas à l'initialisation d'une variable statique dans le .cpp.)
Je m'y connais pas trop en accès concurrent donc..., je sais pas trop. :/
Titre: Re : Bug avec les threads. (Les mutex ne marchent pas dans un certain cas précis.)
Posté par: Laurent le Juillet 30, 2013, 09:59:07 pm
Si tu nous montrais un code minimal de ce que tu fais (qui reproduit bien le problème), on pourrait t'expliquer ce qui se passe.
Titre: Re : Bug avec les threads. (Les mutex ne marchent pas dans un certain cas précis.)
Posté par: Lolilolight le Juillet 31, 2013, 02:06:52 pm
Ok je vais essayer de reprendre le code minimal que j'ai posté plus haut, mais cette fois là avec plusieurs threads, on va voir si ça va crasher.
Titre: Re : Bug avec les threads. (Les mutex ne marchent pas dans un certain cas précis.)
Posté par: Lolilolight le Juillet 31, 2013, 05:18:58 pm
Bon, déjà là j'ai un code qui crash, et pourtant, ma configuration est la même que pour dans mon plus gros projet, j'utilise exactement la même version de SFML.

Le fichier globals.h qui contient le mutex :

#ifndef GLOBALS_H
#define GLOBALS_H
static sf::Mutex globalMutex;
#endif // GLOBAL_H
 

Le fichier mythread.h (c'est ce qui remet à jour la position des entités dans le monde, dans mon plus gros projet.)
#ifndef MY_THREAD
#define MY_THREAD
#include <SFML/System.hpp>
#include "truc.h"
#include "bidule.h"
#include "globals.h"
#include <random>

class MyThread {
public :
    MyThread ();
    void start ();
private :
    void run ();
    Truc* truc;
    sf::Thread m_thread;
};
#endif // MY_THREAD
 

Le fichier mythread.cpp
#include "mythread.h"
using namespace std;
MyThread::MyThread () : m_thread (&MyThread::run, this) {
    truc = Bidule::getTruc();
}
void MyThread::start () {
    m_thread.launch();
}
void MyThread::run () {
    while (true) {
        globalMutex.lock();
        int iVar = rand() % 100;
        truc->setIVar(iVar);
        globalMutex.unlock();
    }
}
 
bidule.h (ce qui correspond au World dans mon plus grand projet.)
#ifndef BIDULE
#define BIDULE
#include "truc.h"
class Bidule {
public :
       static Truc* getTruc() {
           if (truc == nullptr) {
               static Truc *t = new Truc(5);
               return t;
           }
           return truc;
       }
       static int& getIVar ();
       static void setIVar(int ivar);
private :
       static Truc *truc;
};
#endif // BIDULE
 
bidule.cpp.
#include "bidule.h"
Truc* Bidule::truc = nullptr;
int& Bidule::getIVar () {
    return truc->getIVar();
}
void Bidule::setIVar (int iVar) {
    truc->setIVar(iVar);
}
 

le fichier truc.h (ce qui correspond à la map dans mons plus gros projet.)
#ifndef TRUC_H
#define TRUC_H
class Truc {
private:
        int m_iVar;
public:
        Truc (int iVar);
        int& getIVar();
        void setIVar(int ivar);
};
#endif
 
Et le fichier .cpp :
#include "truc.h"
Truc::Truc(int iVar) : m_iVar(iVar) {

}
int& Truc::getIVar() {
       return m_iVar;
}
void Truc::setIVar(int i) {
    m_iVar = i;
}
 

Et la main :
#include <ctime>
#include <random>
#include "mythread.h"
int main () {
    srand(time(NULL));
    MyThread myThread;
    myThread.start();
    return 0;
}
 

Le débugueur me dis ça :

#0 6898174C sf::Mutex::Mutex() () (D:\Projets-c++\TestThreadMutex\bin\Debug\sfml-system-2.dll:??)
#1 004017DD __static_initialization_and_destruction_0(__initialize_p=1, __priority=65535) (D:/Projets-c++/TestThreadMutex/globals.h:3)
#2 00401805 _GLOBAL__sub_I__ZN8MyThreadC2Ev() (D:\Projets-c++\TestThreadMutex\mythread.cpp:14)
#3 0040261A __do_global_ctors () (??:??)
#4 40000060 ?? () (??:??)
#5 0000003D ?? () (??:??)
#6 00962F20 ?? () (??:??)
#7 762333AA KERNEL32!BaseCleanupAppcompatCacheSupport() (C:\Windows\syswow64\kernel32.dll:??)
#8 0028FFD4 ?? () (??:??)
#9 76FB9EF2 ntdll!RtlpNtSetValueKey() (C:\Windows\system32\ntdll.dll:??)
#10 7EFDE000 ?? () (??:??)
#11 76FB9EC5 ntdll!RtlpNtSetValueKey() (C:\Windows\system32\ntdll.dll:??)
#12 004014E0 WinMainCRTStartup () (??:??)
#13 7EFDE000 ?? () (??:??)
#14 ?? ?? () (??:??)

PS : j'ai le même soucis avec les thread du c++11 donc le bug ne vient pas de la SFML mais de je ne sais pas trop ou, une librairie de plus bas niveau sans doute.
Titre: Re : Bug avec les threads. (Les mutex ne marchent pas dans un certain cas précis.)
Posté par: Laurent le Juillet 31, 2013, 06:18:00 pm
Ca plante avant le main(), dans le constructeur de sf::Mutex. Tu n'aurais aucun code autre que la déclaration du mutex, ça planterait aussi... Tu ne t'es pas rendu compte de ça en examinant la pile d'appels ?

Ensuite ce code ne contient qu'un thread en plus du thread principal, et le thread principal ne fait qu'attendre sur le thread. Donc au final ce code est mono-threadé. Il n'y a donc aucun accès concurrent et le mutex ne sert strictement à rien.

Bref, c'est pas encore très concluant ;)
Titre: Re : Bug avec les threads. (Les mutex ne marchent pas dans un certain cas précis.)
Posté par: Lolilolight le Juillet 31, 2013, 06:55:18 pm
Oui heu, j'essaye déja de faire fonctionner un thread tout seul, sans mutex, mais, là, ça ne fonctionne pas...
Même si j'enlève le mutex ça ne marche pas, ça crash dans la méthode launch..., donc, je ne sais pas vraiment faire plus pour le moment tant que je n'aurai pas résolu ce problème.
Titre: Re : Bug avec les threads. (Les mutex ne marchent pas dans un certain cas précis.)
Posté par: Laurent le Juillet 31, 2013, 07:11:42 pm
Ca donne quoi exactement sans le mutex ? (pile d'appels)
Titre: Re : Bug avec les threads. (Les mutex ne marchent pas dans un certain cas précis.)
Posté par: Lolilolight le Juillet 31, 2013, 07:14:53 pm
Ca (ça plante dans la fonction wait.)

#0 689835B1 sf::priv::ThreadImpl::wait() () (D:\Projets-c++\TestThreadMutex\bin\Debug\sfml-system-2.dll:??)
#1 68982B21 sf::Thread::wait() () (D:\Projets-c++\TestThreadMutex\bin\Debug\sfml-system-2.dll:??)
#2 68982B57 sf::Thread::launch() () (D:\Projets-c++\TestThreadMutex\bin\Debug\sfml-system-2.dll:??)
#3 00401702 MyThread::start(this=0x28feb4) (D:\Projets-c++\TestThreadMutex\mythread.cpp:7)
#4 0040165D main() (D:\Projets-c++\TestThreadMutex\main.cpp:7)

Mais pourquoi il faut le fichier .dll hors que je link la librairie en statique ?
Titre: Re : Bug avec les threads. (Les mutex ne marchent pas dans un certain cas précis.)
Posté par: Lolilolight le Juillet 31, 2013, 07:23:44 pm
Bon j'ai trouvé en fait c'est libsfml-system-s.a et pas libsfml-system.a qu'il fallait link, d'habitude c'est des .lib pour le linkage dynamique pour ça que j'ai fait la faute, je vais essayer avec plusieurs thread et le mutex maintenant pour voir.
Titre: Re : Bug avec les threads. (Les mutex ne marchent pas dans un certain cas précis.)
Posté par: Lolilolight le Juillet 31, 2013, 08:21:45 pm
Bon mon code n'est pas encore assez complexe pour reproduire le problème, en fait j'ai un constructeur (classe SrkServer) qui instancie un thread.
Ensuite, dans ce constructeur, je charge la map et je l'ajoute au world.

Ensuite, toujours dans ce même constructeur, j'appelle un 2 ème constructeur (classe SrkChannel.) qui instancie un autre thread. (Donc j'ai un thread qui lis les données reçue par le client, ensuite, un autre thread par canal (le serveur contient plusieurs canaux.)) qui se charge de mettre à jour les entités et envoyer tout au client, j'ai besoin d'un pointeur sur la map dans ma classe SrkChannel pour pouvoir avoir accès à certaines données, pour la mise à jour, comme par exemple, les collisions.

Dans le constructeur ou j'instancie le 1er thread, je charge la map, je l'ajoute à la classe World qui ne contient rien d'autre qu'un std::vector de Map avec toute les maps du jeux, ensuite, j'appelle le constructeur du second thread dans lequel je récupère la map pour que le deuxième thread puisse y avoir accès aussi.

Mais ça crash, je suis obligé d'appelé le constructeur qui instancie le second thread, dans la fonction qui démarre le 1er thread, et non pas dans le constructeur qui instancie le 1er thread, sinon, ça plante.

Je vais essayer de reproduire le crash, avec un code plus simple. (Donc avec un constructeur qui instancie un thread qui fait appel à un constructeur qui instancie un autre thread.)


Titre: Re : Bug avec les threads. (Les mutex ne marchent pas dans un certain cas précis.)
Posté par: Laurent le Juillet 31, 2013, 08:30:15 pm
Citer
Bon j'ai trouvé en fait c'est libsfml-system-s.a et pas libsfml-system.a qu'il fallait link, d'habitude c'est des .lib pour le linkage dynamique
Rien à voir, .a c'est gcc et .lib c'est Visual C++.
Titre: Re : Bug avec les threads. (Les mutex ne marchent pas dans un certain cas précis.)
Posté par: Lolilolight le Juillet 31, 2013, 09:44:44 pm
Ha, ok!
Titre: Re : Re : Bug avec les threads. (Les mutex ne marchent pas dans un certain cas précis.)
Posté par: lefreut le Août 03, 2013, 10:16:54 pm
PS : j'ai le même soucis avec les thread du c++11 donc le bug ne vient pas de la SFML mais de je ne sais pas trop ou, une librairie de plus bas niveau sans doute.

Plutôt que de rejeter la faute sur la SFML puis sur la bibliothèque standard C++, ça ne te parait pas plus plausible que le bug soit dans ton code  ;)

Faire du multithreading est très complexe, à moins de vraiment en avoir besoin et de savoir ce que tu fais, je te conseille de t'en passer.

Au passage, les variables globales et les fonctions statiques (dont ton exemple est rempli) ne font pas bon ménage avec les threads.
Titre: Re : Bug avec les threads. (Les mutex ne marchent pas dans un certain cas précis.)
Posté par: cobra.one le Août 04, 2013, 11:34:25 am
+1000 avec lefreut...

Le "bug" vient à 99,99% de ton code, et encore, en étant gentil ! En plus des conseils de lefreut, j'ajouterai que les accès concurrents mal gérés peuvent causer des crashs dont l'origine est parfois TRES difficile à identifier, pour lesquels même les debuggers se plantent lamentablement. Je parle en connaissance de cause. Moralité : éviter autant que possible les threads, sinon essayer de limiter au maximum les effets de bord en limitant les interactions entre threads, et en rendant le moindre booléen partagé atomique, et les mutex seulement quand c'est absolument nécessaire et en y réfléchissant bien afin d'éviter les interblocages et autres joyeusetés...

Sinon c'est l'usine à gaz assurée, avec un fonctionnement disons... aléatoire.

Enfin dernière chose : si ton code est sensé être portable, teste le bien sur toutes les plateformes cibles au fur et à mesure du développement, parce que rien que concernant la partie concurrente de ton programme, ça va marcher sur le système X, et sur Y pouf... plantage. Idem concernant les "stress tests"... ne pas les oublier parce que tes threads peuvent tourner nickel pendant 2h et tout planter à 2h01, ou bien fonctionner 8h sans souci un jour, et le lendemain planter toutes les 3 minutes.
Titre: Re : Bug avec les threads. (Les mutex ne marchent pas dans un certain cas précis.)
Posté par: Lolilolight le Août 05, 2013, 09:00:06 am
Salut,
oui je sais cela d'ailleurs se serait lourd que le serveur plante toutes les 2h.
Pour le moment, je me suis contenté de instancier créer le second thread dans la méthode start du 1er thread, au lieu de créer le second thread dans le constructeur du 1er thread, et ça ne crash plus, mais je suis pas sûr que c'est une solution qui va vraiment marcher.

Bref je pense que je vais utiliser une variable booléenne plutôt qu'un mutex, ça ira surement mieux.
Titre: Re : Bug avec les threads. (Les mutex ne marchent pas dans un certain cas précis.)
Posté par: Lolilolight le Août 05, 2013, 10:01:00 am
Voilà j'ai réussi à reproduire le crash, ça crash à un moment aléatoire à l'exécution :

Classe bidule : fichier bidule.h

#ifndef BIDULE
#define BIDULE
#include "truc.h"
#include <vector>
class Bidule {
public :
       static Truc* getTruc (std::string name);
       static void addTruc (Truc *truc);
private :
       static std::vector<Truc*> trucs;
};
#endif // BIDULE
 

fichier  bidule.cpp

#include "bidule.h"
using namespace std;
vector<Truc*> Bidule::trucs = vector<Truc*>();
void Bidule::addTruc (Truc * truc) {
    trucs.push_back(truc);
}
Truc* Bidule::getTruc (string name) {
    for (int i = 0; i < trucs.size(); i++)
        if (trucs[i]->getName() == name)
            return trucs[i];
    return nullptr;
}
 

Classe Truc : fichier.h

#ifndef TRUC_H
#define TRUC_H
#include <string>
class Truc {
private:
        int m_iVar;
        std::string m_sName;
public:
        Truc (std::string sName, int iVar);
        int& getIVar();
        void setIVar(int ivar);
        std::string getName();
};
#endif
 

fichier.cpp

#include "truc.h"
using namespace std;
Truc::Truc(string sName, int iVar) : m_iVar(iVar), m_sName(sName) {

}
string Truc::getName() {
    return m_sName;
}
int& Truc::getIVar() {
       return m_iVar;
}
void Truc::setIVar(int i) {
    m_iVar = i;
}
 

Classe MyThread : fichier.h

#ifndef MY_THREAD
#define MY_THREAD
#include <SFML/System.hpp>
#include "truc.h"
#include "bidule.h"
#include "gbls.h"
#include <random>
#include <iostream>
#include "mySecondThread.h"
class MyThread {
public :
    MyThread ();
    void start ();
private :
    void run ();
    Truc* truc;
    sf::Thread m_thread;
    MySecondThread m_secondThread;
};
#endif // MY_THREAD
 

fichier.cpp

#include "mythread.h"
using namespace std;
MyThread::MyThread () : m_thread (&MyThread::run, this) {
    Truc* t = new Truc("TRUC", 5);
    Bidule::addTruc(t);
    truc = Bidule::getTruc("TRUC");
}
void MyThread::start () {
    //m_secondThread = new MySecondThread(20);
    m_thread.launch();
    m_secondThread.start();
}
void MyThread::run () {
    while (true) {
        globalMutex.lock();
        int iVar = rand() % 100;
        truc->setIVar(iVar);
        cout<<"iVar : "<<truc->getIVar()<<endl;
        globalMutex.unlock();
    }
}
 

Classe MySecondThread : fichier.h

#ifndef MY_SECOND_THREAD
#define MY_SECOND_THREAD
class MySecondThread {
public :
    MySecondThread ();
    void start ();
private :
    void run ();
    Truc* truc;
    sf::Thread m_thread;
};
#endif // MY_SECOND_THREAD
 

fichier.cpp

#include "mythread.h"
using namespace std;

MySecondThread::MySecondThread () : m_thread (&MySecondThread::run, this) {
    truc = Bidule::getTruc("TRUC");
}
void MySecondThread::start () {
    m_thread.launch();
}
void MySecondThread::run () {
    while (true) {
        globalMutex.lock();
        int iVar = rand() % 100;
        truc->setIVar(iVar);
        cout<<"iVar : "<<truc->getIVar()<<endl;
        globalMutex.unlock();
    }
}
 

Mon mutex :

#ifndef GBLS_H
#define GBLS_H
#include <SFML/System.hpp>
static sf::Mutex globalMutex;
#endif // GLOBAL_H
 

Et le main :

#include <ctime>
#include <random>
#include "mythread.h"
#include <iostream>
using namespace std;
int main () {
    srand(time(NULL));
    MyThread myThread;
    myThread.start();
    Truc *truc = Bidule::getTruc("TRUC");
    while (true) {
        globalMutex.lock();
        int iVar = rand() % 100;
        truc->setIVar(iVar);
        cout<<"iVar : "<<truc->getIVar()<<endl;
        globalMutex.unlock();
    }
    return 0;
}
 

Voilà, si j'utilise un pointeur sur MySecondThread dans la classe MyThread et que je crée le thread plus tard ça ne crash plus mais je ne sais pas si c'est une bonne solution pour régler le problème car ça pourrait planter sur un autre OS ou bien planter au bout de 2h.


PS : ça crash aussi à différents moment si je lance le débugueur ou pas : si je lance le débugueur ça crash tout de suite, sinon, si je le lance normalement ça crash plus tard.

PS 2 : voilà donc comment faire du code qui crash de manière aléatoire.  :D
Titre: Re : Bug avec les threads. (Les mutex ne marchent pas dans un certain cas précis.)
Posté par: Laurent le Août 05, 2013, 10:18:39 am
C'est normal que ça crashe, et ça n'a rien à voir avec le multi-threading : m_secondThread est construit avant l'appel à Bidule::addTruc, du coup il récupère puis utilise un pointeur nul.

Pense à utiliser ton debugger, un pointeur nul c'est facile à repérer.
Titre: Re : Bug avec les threads. (Les mutex ne marchent pas dans un certain cas précis.)
Posté par: Lolilolight le Août 05, 2013, 10:24:37 am
Ha oui juste!

Pour ça que ça plantais dans mon plus gros projet alors, sauf que là il ne m'indiquait pas de pointeur null le débugueur...

Bref j'ai enfin compris pourquoi ça buguais et que je devais créer mon second thread plus tard. (Car sinon il récupèrais un pointeur null.)

Titre: Re : Re : Bug avec les threads. (Les mutex ne marchent pas dans un certain cas précis.)
Posté par: cobra.one le Août 05, 2013, 05:20:31 pm
Bref je pense que je vais utiliser une variable booléenne plutôt qu'un mutex, ça ira surement mieux.

 :o

Un booléen, de base, n'est ni atomique, ni thread-safe... donc je ne vois pas trop comment il peut remplacer un mutex...
Titre: Re : Bug avec les threads. (Les mutex ne marchent pas dans un certain cas précis.)
Posté par: Lolilolight le Août 06, 2013, 11:32:26 am
Bah tu mets le booléen à false quand tu veux que ton thread bloque l'accès et à true quand ton thread à fini. (Mais cette variable booléenne doit être unique, donc statique, et accessible partout, donc, globale.)

Mais il reste un problème, les autres threads doient être mis en attente en attendant que le thread courant soit déverouillé et ça je vois pas comment faire, le verrou c'est simple c'est juste une variable booléenne mais pour le reste je ne sais pas comment ça fonctionne.

Je pensais faire ça parce que même en créant mon objet "secondThread" plus tard en l'allouant dynamiquement, pour que le pointeur sur mon objet truc ne soit pas null, ça plante quand même dans mon plus gros code, quand y'a plus de risque d'accès concurrents, d'ailleurs je vais faire un stress test avec ce petit bout de code si j'alloue mon objet seconde thread dynamiquement dans le constructeur pour voir...
Parce que y'a un truc que je ne comprend pas je fais exacement pareil dans les 2 codes, avec l'un ça fonctionne, avec l'autre ça plante.

Et atomique c'est le contraire de composé donc un booléen est bien atomique vu qu'il n'est pas composé de plusieurs autres variables. (Tout comme tout les autres type primitifs du c++, int, long, short, char, etc..)
Et je crois pas que le booléen ai besoin d'être thread safe mais il me semble qu'il existe un mot clé en c++ pour rendre une variable thread safe, ou je me trompe ?

PS : par contre le endl ne marche pas toujours dans la console, j'ai bien mis un endl dans les 3 threads, ça, c'est bizarre.
Titre: Re : Bug avec les threads. (Les mutex ne marchent pas dans un certain cas précis.)
Posté par: Laurent le Août 06, 2013, 11:51:55 am
Tu devrais vraiment potasser quelques articles / tutoriels concernant les threads et les accès concurrents.

Le standard C++ ne spécifie pas qu'une lecture ou écriture de booléen soit atomique. Si c'est le cas, alors ce sera uniquement parce que la plateforme particulière sur laquelle tu exécutes ton code le garantit. Du coup il vaut mieux ne pas en faire l'hypothèse par défaut, et considérer que seul std::atomic<T> est atomique.

Du coup, si ton booléen protège ton code, qui protège ton booléen ? Tu tournes en rond avec ce genre de raisonnement, il y a un moment où il faut forcément introduire une primitive de synchronisation (mutex ou autre).

Et quant à refaire un mutex from scratch... tu crois vraiment que ce sont les mutexs systèmes / SFML qui sont buggés et pas ton code ? Sérieusement, si je peux te donner un conseil, arrête de penser comme ça et remets-toi un peu en question. Ici on veut bien t'aider mais il faut que tu y mettes un peu de bonne volonté. Arrête-toi un peu, potasse de la doc, comprends les choses et ensuite on pourra tranquillement se pencher sur les éventuels problèmes qu'il te restera.
Titre: re
Posté par: Lolilolight le Août 06, 2013, 12:32:38 pm
Ouiais, bref, c'est bizarre, le débugueur ne me donne pas beaucoup d'infos :

#0 ?? CellMap::getCenter (this=0xabababab) (D:\Projets-c++\SorrokSrv\world\mapCell.cpp:91)
#1 0043D648 GridMap::getPath(this=0x2b400e0, startPos=..., finalPos=...) (D:\Projets-c++\SorrokSrv\world\gridMap.cpp:425)
#2 0042D2E4 SrkChannel::run(this=0x2be4a78) (D:\Projets-c++\SorrokSrv\NetworkEngine\srkchannel.cpp:76)
#3 00E9A3C8 ?? () (??:??)
#4 ?? ?? () (??:??)

Et ça ne plante que quand je lance le débugueur, quand je le lance normalement ça ne plante pas.

Donc le problème vient peut être ailleurs que dans les mutex et les threads, en fait, je sais pas vraiment d'ou ça vient. :/

Peut être d'ici ?
#include "boundingPolygon.h"
BoundingPolygon::BoundingPolygon () : center(0, 0) {
}
BoundingPolygon::BoundingPolygon (const BoundingPolygon &bp) {
    for (unsigned int i = 0; i < points.size(); i++)
        delete points[i];
    points.clear();
    for (unsigned int i = 0; i < bp.points.size(); i++)
        addPoint(new Vec2f(*bp.points[i]));
    computeCenter();
}
void BoundingPolygon::addPoint(Vec2f *point) {
    points.push_back(point);
    computeCenter();
}
bool BoundingPolygon::isPointInside(Vec2f &p) {

    /*On calcule le nombre d'intersections avec une demi-droite
    *partant du point p vers le haut, et les segments du polygône.
    *Si le nombre d'intersections est impair, alors le point est dans le polygône!
    *          |
    *          /\
    *         /| \
    *        / |  \
    *        \ .  /
    *         \  /
    *          \/
    */

    int nbIntersections = 0;
    Vec2f i;
    i.x = 10000 + rand() % 100;
    i.y = 10000 + rand() % 100;

    for (unsigned int n = 0; n < points.size() ; n++) {
        Vec2f a = *points[n];
        Vec2f b;
        if (n == points.size() - 1)
            b = *points[0];
        else
            b = *points[n + 1];
        Segment s1 (a, b);
        Segment s2 (i, p);
        int iseg = s1.intersects(s2);
        if (iseg == -1)
            return isPointInside(p);
        nbIntersections += iseg;
    }
   //Si le nombre d'intersections est impaire alors le point est dans le polygône.
   return nbIntersections % 2 != 0;
}
unsigned int BoundingPolygon::nbPoints () {
    return points.size();
}
bool BoundingPolygon::intersects (BoundingRectangle &br) {
    Vec2f pts[4];
    pts[0] = Vec2f (br.getPosition().x, br.getPosition().y);
    pts[1] = Vec2f (br.getPosition().x + br.getWidth(), br.getPosition().y);
    pts[2] = Vec2f (br.getPosition().x + br.getWidth(), br.getPosition().y + br.getHeight());
    pts[3] = Vec2f (br.getPosition().x, br.getPosition().y + br.getHeight());

    for (int i = 0; i < 4; i++) {
       Vec2f v1 = pts[i];
       Vec2f v2;
       if (i == 3)
           v2 = pts[0];
       else
           v2 = pts[i + 1];
       Segment s1 (v1, v2);
       for (unsigned int j = 0; j < points.size(); j++) {
            Vec2f v3 = *points[j];
            Vec2f v4;
            if (j == points.size() - 1)
                v4 = *points[0];
            else
                v4 = *points[j+1];
            Segment s2 (v3, v4);

            if (s1.intersects(s2) > 0.f) {

                return true;
            }
       }
    }
    return false;
}
void BoundingPolygon::computeCenter () {
    Vec2f sum(0.f, 0.f);
    for (unsigned int i = 0; i < points.size(); i++) {
        if (points[i] != NULL)
            sum += *points[i];
    }
    center = sum / points.size();

}
BoundingPolygon BoundingPolygon::operator= (const BoundingPolygon &bp) {
    for (unsigned int i = 0; i < points.size(); i++)
        delete points[i];
    points.clear();
    for (unsigned int i = 0; i < bp.points.size(); i++)
        addPoint(new Vec2f(*bp.points[i]));
    computeCenter();
    return *this;
}
BoundingPolygon::~BoundingPolygon () {
    for (unsigned int i = 0; i < points.size(); i++) {
        delete points[i];

    }
    points.clear();

}
bool BoundingPolygon::operator== (const BoundingPolygon &bp) {
    if(points.size() != bp.points.size())
        return false;
    for (unsigned int i = 0; i < points.size(); i++) {
        if (!(*points[i] == *bp.points[i])) {
            return false;
        }
    }
    return true;
}
Vec2f BoundingPolygon::getPoint(unsigned int index) {
    if (index >= 0 && index < points.size())
        return *points[index];
    return Vec2f (0, 0);
}
Vec2f BoundingPolygon::getCenter () {
    return center;
}
 

#include "mapCell.h"
using namespace std;
CellMap::CellMap (BoundingPolygon *bp, Vec2f coords) {
    entityInside = vector<vector<Entity*> >(NB_LAYERS);
    poly = bp;
    center = poly->getCenter();
    this->coords = coords;
    passable = true;
    stateChanged = false;
    traveled = false;
}
Vec2f CellMap::getCenter () {
    return center;
}
 

Mais je sèche je vois pas du tout ce qui pourrait planter avec la variable center.
Titre: Re : Bug avec les threads. (Les mutex ne marchent pas dans un certain cas précis.)
Posté par: Laurent le Août 06, 2013, 12:44:04 pm
Le debugger te donne pas mal d'infos : il te dit que dans GridMap::getPath tu appelles la fonction getCenter sur une instance de CellMap non-initialisée.
Titre: Re : Bug avec les threads. (Les mutex ne marchent pas dans un certain cas précis.)
Posté par: Lolilolight le Août 06, 2013, 12:56:21 pm
Ha, mais ou t'a vu qu'il a marqué ça ?
Titre: Re : Bug avec les threads. (Les mutex ne marchent pas dans un certain cas précis.)
Posté par: Laurent le Août 06, 2013, 01:30:39 pm
Citer
#0 ??   CellMap::getCenter (this=0xabababab) (D:\Projets-c++\SorrokSrv\world\mapCell.cpp:91)
Ici on voit que le crash est survenu directement dans cette fonction. La valeur 0xabababab pour "this" est une valeur spéciale, donc elle a une signification spéciale. Une rapide recherche montre que pour gcc, elle signifie "espace mémoire non initialisé".

Ensuite en remontant d'un cran dans la pile d'appels, on voit que l'appel foireux a été fait dans la fonction GridMap::getPath, et que celle-ci possède par contre un "this" a priori valide (parfois les "this" foireux s'imbriquent sur plusieurs niveaux, avant que ça crashe).
Titre: Re : Bug avec les threads. (Les mutex ne marchent pas dans un certain cas précis.)
Posté par: Lolilolight le Août 06, 2013, 01:53:52 pm
Ha je ne savais pas que cette valeur était une valeur spéciale pour "this".

C'est encore différent de la valeur null dans ce cas ? :/

Et comment puis je repéré si une cellMap n'est pas initialisée dans le programme ? (Car mes CellMap sont dont un std::vector, et c'est possible que mon std::vector contienne des cases vide.)

Je pensais que c'était automatiquement initialisé à null dans ce cas mais apparemment non. :/

Titre: Re : Bug avec les threads. (Les mutex ne marchent pas dans un certain cas précis.)
Posté par: Laurent le Août 06, 2013, 02:04:31 pm
Citer
C'est encore différent de la valeur null dans ce cas ?
"null" fait parti du langage, c'est le pointeur qui vaut zéro.

Là c'est différent : c'est le compilateur qui te donne un coup de pouce en debug, au lieu de laisser une zone mémoire avec du contenu aléatoire, il y met quelque chose qui te permettra d'avoir des informations en cas de bug. C'est complètement interne au compilateur comme fonctionnalité, cela n'a rien à voir avec le langage.

Typiquement, tu peux avoir des valeurs spéciales pour :
- de la mémoire non allouée
- de la mémoire désallouée
- de la mémoire en dehors de la pile
- etc.

Citer
Et comment puis je repéré si une cellMap n'est pas initialisée dans le programme
Pour ça il faut inspecter le code source correspondant.

Tu peux aussi utiliser des outils dédiés, comme valgrind.
Titre: Re : Bug avec les threads. (Les mutex ne marchent pas dans un certain cas précis.)
Posté par: Lolilolight le Août 06, 2013, 02:34:10 pm
Erf valgrind ne marche pas sous windows. :/

Pour une raison que j'ignore, mes CellMap ne sont pas bien initialisée dans mon thread. (Lorsque j'initialise le thread, dans le constructeur de mon autre thread, si j'initialise ailleurs ça marche.)

Et pourtant j'initialise tout en même temps, la map, les cellMaps, etc...

La map est bien initialisée vu que le pointeur est valide mais les CellMap ne le sont pas.

Faudrait que je trouve un outil du genre mais pour windows, ou alors que je passe sous linux pour trouver le problème. (Ca ne plantera peut être pas sous linux xd.)
Titre: Re : re
Posté par: cobra.one le Août 06, 2013, 11:01:52 pm
Et ça ne plante que quand je lance le débugueur, quand je le lance normalement ça ne plante pas.

[...]

Pour une raison que j'ignore, mes CellMap ne sont pas bien initialisée dans mon thread. (Lorsque j'initialise le thread, dans le constructeur de mon autre thread, si j'initialise ailleurs ça marche.)


Je n'ai pas suffisamment d'éléments pour être catégorique, mais ce genre de crash non systématique ressemble fortement à un problème dû à une mauvaise synchronisation de threads... Attention au fait qu'il n'y a aucune garantie quant à l'ordre d'exécution des threads.

Il ne faut donc pas s'attendre à ce que le code s'exécute tel qu'il est écrit. Ca n'est pas parce qu'un thread T1 est lancé avant un thread T2 dans le code qu'il y a la garantie du système que T1 commencera bien à s'exécuter avant T2. C'est "possible", mais pas "certain". Avec de probables conséquences sur les ressources créées par un thread et accédées par un autre...
Titre: Re : Bug avec les threads. (Les mutex ne marchent pas dans un certain cas précis.)
Posté par: Lolilolight le Août 07, 2013, 12:48:20 pm
Pourtant, j'instancie tout dans le thread principale (le main), donc, normalement, tout est bien instancier avec l'ordre dans lequel j'écris le code, mais ici, je viens de rajouter, un pnj à mon word, et quand je veux récupérer le nom du pnj dans le constructeur, paf, plantage!

Voici un petit bout de code qui montre le problème :

La classe qui contient le 1er thread (en variable membre.) :

#include "network.h"

using namespace sf;
using namespace std;

SrkServer::SrkServer(int nbChannels) : m_thread(&SrkServer::run, this)
{
    this->nbChannels = nbChannels;
    running = false;
    Pnj *pnj = new Pnj (Vec2f (500, 500), Vec2f (50, 100), Entity::E_PNJ, "Mafus");
    UpsMapLoader loader("Maps/test.upsmap");
    Map *map = new Map();
    if (loader.createMap(*map,map->getLightManager(), map->getImageManager())) {
        map->gridMap->addPnj(pnj);
        World::addMap(map);
    } else {
        delete map;
    }
    ostringstream oss;
    oss<<"Ho, un nouveau!  Bienvenue dans le monde de Dorikasa!!! Voici votre première quête!";
    oss<<"Les sphérix sont des monstres venu du des Sorokiens, pouvais vous m'en tuer, 10 suffiront.";
    oss<<"Ces monstres mécanique ont le malheur de toujours piétiner mes cultures.";
    Quest* quest = new Quest (oss.str(), 5000);
    pnj->addQuest(quest);

}
void SrkServer::startSrv(int portTCP, int portUDP) {
    for (int i = 0; i < nbChannels; i++) {
        SrkChannel *channel = new SrkChannel(*this, "Channel "+conversionIntString(i+1));
        channels.push_back(channel);

    }
    for (unsigned int i = 0; i < channels.size(); i++) {
        channels[i]->start();
    }
    if (!running) {

        if (!udpSocket.bind(portUDP) == Socket::Done) {
            cerr<<"Impossible d'écouter sur ce port : "<<portUDP<<endl;
        } else {
            selector.add(udpSocket);
        }
        if (!listener.listen(portTCP) == Socket::Done) {
            cerr<<"Impossible d'écouter sur ce port : "<<portTCP<<endl;
        } else {
            cout<<"Server started!"<<endl;
            selector.add(listener);
            m_thread.launch();
        }

    } else {
        cout<<"Server already started!"<<endl;
    }

}
 

Et celle qui contient le second thread en variable membre :

#include "srkchannel.h"
#include "user.h"
#include "../IA/ia.h"
using namespace std;
using namespace sf;
SrkChannel::SrkChannel(SrkServer &server, string name) : server(server), name (name), m_thread(&SrkChannel::run, this)
{
     this->map = World::getMap("Map test");
    BoundingRectangle mZoneInf(200, 200, 500, 500);
    int posX, posY;
    Vec2f isoCoords;
    do {
        posX = rand() % (int) mZoneInf.getWidth();
        posY = rand() % (int) mZoneInf.getHeight();
        isoCoords = Math::convertTo2DIsoCoords(Vec2f (posX, posY) - mZoneInf.getPosition());
        isoCoords += mZoneInf.getPosition();
    } while (map->gridMap->getGridCellAt(isoCoords) == NULL || !map->gridMap->getGridCellAt(isoCoords)->isPassable());

    BoundingPolygon mZone;
    Vec2f** points = new Vec2f*[4];
    points[0] = new Vec2f(mZoneInf.getPosition());
    Vec2f tmp1 = Math::convertTo2DIsoCoords(Vec2f(mZoneInf.getWidth(), 0));
    points[1] = new Vec2f (tmp1 + mZoneInf.getPosition());
    Vec2f tmp2 = Math::convertTo2DIsoCoords(Vec2f(mZoneInf.getWidth(), mZoneInf.getHeight()));
    points[2] = new Vec2f (tmp2 + mZoneInf.getPosition());
    Vec2f tmp3 = Math::convertTo2DIsoCoords(Vec2f (0, mZoneInf.getHeight()));
    points[3] = new Vec2f (tmp3 + mZoneInf.getPosition());
    for (unsigned int i = 0; i < 4; i++) {
        mZone.addPoint(points[i]);
    }
    Monster *m = new Monster (isoCoords, mZoneInf, mZone, 1, 100);
    m->setCenter(isoCoords);

    Time t = seconds(5.f);
    m->setTime(t);
    monsters.push_back(m);
    map->gridMap->getPnj("Mafus")->getQuests()[0]->addMonsterToKill(m, 10);
    tmpDist = 0;
    running = false;
}
void SrkChannel::start () {
    m_thread.launch();
}
 

J'ai un plantage à cette ligne-ci :

map->gridMap->getPnj("Mafus")->getQuests()[0]->addMonsterToKill(m, 10);
 

Et le débugueur m'afficher une erreur, vraiment bizarre. :/

#0 6FC83FAA ??() (D:\Projets-c++\SorrokSrv\bin\Debug\libstdc++-6.dll:??)
#1 ?? 0x004456d5 in Pnj::getName (this=0x440b02 <GridMap::getPnj(std::string)+210>) (D:\Projets-c++\SorrokSrv\world\pnj.cpp:13)
#2 015DA66C ?? () (??:??)
#3 FEEEFEEE ?? () (??:??)
#4 FEEEFEEE ?? () (??:??)
#5 FEEEFEEE ?? () (??:??)
#6 FEEEFEEE ?? () (??:??)
#7 FEEEFEEE ?? () (??:??)
#8 FEEEFEEE ?? () (??:??)
#9 FEEEFEEE ?? () (??:??)
#10 FEEEFEEE ?? () (??:??)
#11 FEEEFEEE ?? () (??:??)
#12 FEEEFEEE ?? () (??:??)
#13 FEEEFEEE ?? () (??:??)
#14 FEEEFEEE ?? () (??:??)
#15 FEEEFEEE ?? () (??:??)
#16 FEEEFEEE ?? () (??:??)
#17 FEEEFEEE ?? () (??:??)
#18 FEEEFEEE ?? () (??:??)
#19 FEEEFEEE ?? () (??:??)
#20 FEEEFEEE ?? () (??:??)
#21 FEEEFEEE ?? () (??:??)
#22 FEEEFEEE ?? () (??:??)
#23 FEEEFEEE ?? () (??:??)
#24 FEEEFEEE ?? () (??:??)
#25 FEEEFEEE ?? () (??:??)
#26 FEEEFEEE ?? () (??:??)
#27 FEEEFEEE ?? () (??:??)
#28 FEEEFEEE ?? () (??:??)
#29 FEEEFEEE ?? () (??:??)

PS : je fais un test sur le nom du pnj pour récupérer le pnj dans la grille.
Titre: Re : Bug avec les threads. (Les mutex ne marchent pas dans un certain cas précis.)
Posté par: Lolilolight le Août 07, 2013, 01:01:49 pm
Non c'est bon j'ai trouvé en ce qui concerne le plantage j'avais inversé 2 arguments dans une fonction..., pour récupérer le pnj de mon vector.

Mais quand je mets ça :
for (int i = 0; i < nbChannels; i++) {
     SrkChannel *channel = new SrkChannel(*this, "Channel "+conversionIntString(i+1));
     channels.push_back(channel);
}
 

Dans le constructeur de SrkServer, c'est là que ça plante mais ça ne plante que en lançant le débugueur et je ne comprends pas pourquoi. :/

Du coup pour débuguer je suis obligé de le mettre dans la méthode startSrv, pas que ça me pose problème mas bon.^^
Titre: Re : Bug avec les threads. (Les mutex ne marchent pas dans un certain cas précis.)
Posté par: cobra.one le Août 07, 2013, 07:04:03 pm
De toute façon selon le message d'erreur que tu nous avais indiqué, tu as un bout de code qui tente d'accéder à la méthode getCenter d'une CellMap qui n'est pas initialisée au moment où l'appel est effectué... ça ne doit pas être bien difficile à retrouver dans le code... :-\
Titre: Re : Bug avec les threads. (Les mutex ne marchent pas dans un certain cas précis.)
Posté par: Lolilolight le Août 07, 2013, 07:08:59 pm
Bah je trouve pas, j'ai initialisé toutes mes CellMap avec le pointeur NULL dans mon std::vector, donc, il ne devrait pas y avoir de CellMap qui ne soit pas initialisée. :/

Titre: Re : Bug avec les threads. (Les mutex ne marchent pas dans un certain cas précis.)
Posté par: Cpl.Bator le Août 07, 2013, 08:05:52 pm
 Tes titres de topic ne sont pas explicites, celui qui ne connais pas la SFML pense qu'elle est bourrée de bugs alors que le problème c'est l'interface chaise / clavier.
Tu devrais faire attention à ce point, ne serait ce que par respect pour l'auteur de la librairie qui le fait à titre gracieux & c'est précieux ;)
Titre: Re : Bug avec les threads. (Les mutex ne marchent pas dans un certain cas précis.)
Posté par: cobra.one le Août 07, 2013, 08:15:39 pm
Bah je trouve pas, j'ai initialisé toutes mes CellMap avec le pointeur NULL dans mon std::vector, donc, il ne devrait pas y avoir de CellMap qui ne soit pas initialisée. :/



 :o

J'ai bien lu ? Tu as donc des CellMap* stockées dans un std::vector, qui valent NULL, et tu tentes d'appeller des méthodes dessus ?
Titre: Re : Bug avec les threads. (Les mutex ne marchent pas dans un certain cas précis.)
Posté par: Lolilolight le Août 08, 2013, 12:23:57 pm
Non, je fais un test (if cellMap != NULL) avant d'appeler des méthode dessus mais apparemment c'est pas NULL mais cette valeur bizarre (0xabababab) que mes pointeurs ont, et je comprends pas pourquoi. (On dirait que je les initialise à NULL mais que la valeur du pointeur change dans la méthode run de mon second thread hors que je ne change pas mes pointeurs entre temps.)

J'ai pensé à un accès concurrant mais même en mettant des mutex tout partout, ça ne résous pas le problème.

Je pencherai donc plutôt pour un bug avec gdb (le débugueur de code::block.) ou alors un bug avec les threads mais au niveau OS plutôt, mais je dirai gdb plutôt vu que ça ne plante pas quand je lance pas le débugueur.
Bref il faudra que je prenne le temps de test ça sous linux avec valgind peut être que là j'aurai plus d'infos.
Titre: Re : Bug avec les threads. (Les mutex ne marchent pas dans un certain cas précis.)
Posté par: Laurent le Août 08, 2013, 12:46:59 pm
Et au fait, pourquoi tu ne nous montres pas la fonction qui plante (GridMap::getPath) ?
Titre: Re : Bug avec les threads. (Les mutex ne marchent pas dans un certain cas précis.)
Posté par: Lolilolight le Août 08, 2013, 01:48:39 pm
Ok, j'aurai pu faire une fonction récursive aussi pour getPath :

vector<Vec2f> GridMap::getPath (Vec2f startPos, Vec2f finalPos) {

    vector<Vec2f> positions;
    positions.push_back(startPos);
    Vec2f currentPos = getGridCellAt(startPos)->getCenter();

    vector<CellMap*> children;
   //Si le joueur a cliqué sur une case ou il y a collision, on recherche la case qui est le plus près de la collision.
    while (!getGridCellAt(finalPos)->isPassable()) {

        vector<CellMap*> children = getNeightbours(getGridCellAt(finalPos), true);

        int distMin = children[0]->getCenter().computeDist(getGridCellAt(startPos)->getCenter());
        int indMin = 0;
        for (unsigned int i = 1; i < children.size(); i++) {
            int dist = children[i]->getCenter().computeDist(getGridCellAt(startPos)->getCenter());
            if (dist < distMin) {
                distMin = dist;
                indMin = i;
            }
        }
        finalPos = children[indMin]->getCenter();
    }


    //Tant qu'on est pas arrivé sur la case finale.
    while (getGridCellAt(currentPos) != getGridCellAt(finalPos)) {
        //On recherche les cases fils. (ou voisines.)

        CellMap *parent = getGridCellAt(currentPos);
        parent->setTraveled(true);
        vector<CellMap*> children = getNeightbours(parent, false);
        unsigned int j = 0;
        while (j < children.size() && children[j]->isTraveled())
            j++;
       //On recherche la case la plus proche de la position finale et on l'ajoute au path.
        int distMin = children[j]->getCenter().computeDist(finalPos);
        int indMin = j;
        for (unsigned int i = j+1; i < children.size(); i++) {
            if (!children[i]->isTraveled()) {
                int dist = children[i]->getCenter().computeDist(finalPos);
                if (dist < distMin) {
                    distMin = dist;
                    indMin = i;
                }
            }
        }

        positions.push_back(children[indMin]->getCenter());
        parent = children[indMin];
        currentPos = parent->getCenter();

    }
    positions.pop_back();
    positions.push_back(finalPos);
    for (unsigned int i = 0; i < casesMap.size(); i++) {
        if (casesMap[i] != NULL)
            casesMap[i]->setTraveled(false);
    }
    return positions;
}
 

Cette fonction utilise une autre fonction :

//Récupère les cases voisines à la case donnée. (si getOnCellPassable vaut tru ça renvoie aussi les cases ou il y a collision.)
vector<CellMap*> GridMap::getNeightbours(CellMap *cell, bool getCellOnPassable) {
    Vec2f coords = cell->getCoords();
    vector<CellMap*> neightbours;

    for (int i = coords.x - 1; i <= coords.x + 1; i++) {
        for (int j = coords.y - 1; j <= coords.y + 1; j++) {
            if (!(i == coords.x && j == coords.y)) {
                Vec2f neightbourCoords(i, j);
                CellMap *neightbour = getGridCellAtFromCoords(neightbourCoords);
                if (neightbour != NULL) {
                    if (getCellOnPassable)
                        neightbours.push_back(neightbour);
                    else if (neightbour->isPassable())
                        neightbours.push_back(neightbour);
                }
            }
        }
    }
    return neightbours;
}
 
Pourtant je test bien si mes cases sont pas vide avant de les ajouté au vecteur, mes cases sont vide si il n'y a rien dessus sur la map et donc si il n'y a rien ou bien si il y a collision le monstre ne peux pas se déplacer dessus.

Titre: Re : Bug avec les threads. (Les mutex ne marchent pas dans un certain cas précis.)
Posté par: Laurent le Août 08, 2013, 01:53:52 pm
Et la ligne 425, c'est laquelle ?

Citer
Pourtant je test bien si mes cases sont pas vide avant de les ajouté au vecteur
C'est pas le problème, le debugger dit que tu accèdes à de la mémoire non-initialisée, pas à un pointeur nul. Donc je pencherai plutôt pour un accès hors bornes, dans l'un des tableaux renvoyés par la fonction getNeightbours.

PS : neighbour n'a pas de "t".
Titre: Re : Bug avec les threads. (Les mutex ne marchent pas dans un certain cas précis.)
Posté par: Lolilolight le Août 08, 2013, 02:00:22 pm
C'est celle-ci :

int distMin = children[j]->getCenter().computeDist(finalPos);
 

Il me dit que children[j] n'est pas initialisé. (Ce code tourne dans un thread.)
Titre: Re : Bug avec les threads. (Les mutex ne marchent pas dans un certain cas précis.)
Posté par: Lolilolight le Août 08, 2013, 02:09:41 pm
Bon je pense que y'avais bien un accès hors borne, car, j'ai oublié un petit j-- :

while (j < children.size() && children[j]->isTraveled())
            j++;
        j--;
 

En effet si la taille du vecteur vaut 1, quand il va rentrer dans la boucle j va valoir 1 et c'est en dehors du vecteur donc je dois faire un j--;

Mais maintenant j'ai une autre erreur :
#0 ?? CellMap::getCenter (this=0x1800dd49) (D:\Projets-c++\SorrokSrv\world\mapCell.cpp:91)
#1 004437E9 GridMap::getPath(this=0x2d20160, startPos=..., finalPos=...) (D:\Projets-c++\SorrokSrv\world\gridMap.cpp:459)
#2 0042E867 SrkChannel::run(this=0x2dc7638) (D:\Projets-c++\SorrokSrv\NetworkEngine\srkchannel.cpp:78)
#3 011CA678 ?? () (??:??)
#4 ?? ?? () (??:??)

Toujours à cette même ligne.
Titre: Re : Bug avec les threads. (Les mutex ne marchent pas dans un certain cas précis.)
Posté par: Laurent le Août 08, 2013, 02:17:54 pm
Tu es sûr que c'est la même ligne ? Maintenant il plante sur la ligne 459.
Titre: Re : Bug avec les threads. (Les mutex ne marchent pas dans un certain cas précis.)
Posté par: Lolilolight le Août 08, 2013, 03:44:48 pm
J'ai changer mon code depuis mes anciens post et j'ai rajouté un truc donc ce n'est plus la même ligne que avant dans le fichier mais c'est exactement à la même ligne de code.

A priori mes this sont valide là pourtant donc c'est surement ailleurs que ça pante.
J'ai essayer de mettre des mutex.lock et unlock dans cette fonction mais ça ne résoud pas le problème.

Bon j'ai rajouté ça pour être sur que j ne sois pas plus petit que 0 non plus mais ça ne résous pas le crash, maintenant ça crash tout le temps que ça soit avec le débugueur ou pas. :o

while (j < children.size() && children[j]->isTraveled())
            j++;
        j--;
        j = (j < 0) ? 0 : j;
 
Titre: Re : Bug avec les threads. (Les mutex ne marchent pas dans un certain cas précis.)
Posté par: Laurent le Août 08, 2013, 03:48:31 pm
Le this a l'air bizarre, même si c'est moins évident. Il n'est pas du tout dans la même plage d'addresse que les autres this.

Mets un point d'arrêt sur la ligne qui plante, et inspecte les membres de children[j] (du coup il faudra sans doute que tu le mettes dans une variable locale d'abord). S'ils sont tous choucroutés, c'est que tu as encore une instance moisie.
Titre: Re : Bug avec les threads. (Les mutex ne marchent pas dans un certain cas précis.)
Posté par: Lolilolight le Août 08, 2013, 03:53:50 pm
Humm, comment que je fais pour voir les variables membres de children[j] ???
Titre: Re : Bug avec les threads. (Les mutex ne marchent pas dans un certain cas précis.)
Posté par: Lolilolight le Août 08, 2013, 03:58:30 pm
Ha non c'est bon j'ai trouvé quand la taille du vecteur vaut 0 je fais un j-- donc, quand il ne rentre pas dans la boucle, ce qui fait que j vaut -1 mais comme je l'ai déclaré en unsigned int, il ne peut pas valoir -1, du coup, ça plantait.

Je m'attendais quand même à un crash tout le temps au départ même sans lancer le débugueur, comme quoi...

Y'a pas moyen de faire en sorte que le compilateur balance une erreur quand on a un unsigned int qui devient négatif par erreur, j'ai cherché pendant des heures  cause de ça. :/
Titre: Re : Bug avec les threads. (Les mutex ne marchent pas dans un certain cas précis.)
Posté par: Laurent le Août 08, 2013, 04:08:06 pm
Citer
Y'a pas moyen de faire en sorte que le compilateur balance une erreur quand on a un unsigned int qui devient négatif par erreur
Nop.

Par contre je peux te donner un conseil : quand ce genre de fonction alambiquée plante, fais une exécution pas à pas avec le debugger, en inspectant les variables locales qui sont utilisées au fur et à mesure. On ne peux pas tout voir simplement en scrutant le code, notamment les cas limites (tableau vide, ...).

Bref, la prochaine fois, au lieu de te précipiter sur le forum pour dire que les mutexs de l'OS sont buggés, que SFML ne marche pas ou autre, prends le temps de faire de vraies session de debugging pour comprendre ce qui se passe dans ton code.
Titre: Re : Bug avec les threads. (Les mutex ne marchent pas dans un certain cas précis.)
Posté par: Lolilolight le Août 08, 2013, 05:00:31 pm
Désolé Laurent j'ai appris à bien programmé. (faire des bons design de code source, des commentaires, des rapports, des diagrammes et tout ce que tu veux mais à aucun moment on m'a appris à me servir du débugueur, chose que j'ai toujours reproché à ma formation.)

Ca avait l'air plutôt d'être des cours du genre : on fait l'analyse, on écris toute la sturcture du code et puis tout le code spécifique au langage de programmation sur papier (enfin au début du moins.) puis on le recopie sur ordinateur et quand on recopie le code sur ordinateur ça doit marcher du 1er coup.

Ce qui était assez absurde, bref..., mais bon voilà maintenant tu sais comment j'ai été formé et on avait pas toujours beaucoup de temps, et tu sais aussi comment ça se passe dans le monde non libre. (c'est à dire dans le monde commercial parce que c'était aussi des études orienté commerce vu que j'étais dans la catégorie économique en informatique de gestion.)
Bref osef de ma vie, cependant j'ai remarqué, pas un bug, ni un crash cette fois mais un beau petit freeze agaçant par moment quand on bouge la vue..., mais ça, ça a déja été dis dans un autre sujet je pense.

Mon personnage parfois arrête de bouger pendant un petit moment. (le FPS ne change pas par contre il est toujours bon.) puis il se tp direct à sa destination. :/)
Y'a des trucs qui ont été modifié dans la SFML 2.1 à propos de ça ou pas ?
Ca me le fait pas tout le temps mais quand même assez fréquement parfois.
Titre: Re : Bug avec les threads. (Les mutex ne marchent pas dans un certain cas précis.)
Posté par: Laurent le Août 08, 2013, 05:40:34 pm
Avoir des lacunes en techniques de debugging, et tout mettre systématiquement sur le dos de SFML et/ou de l'OS, ce sont deux choses très différentes ;)

En ce qui concerne ton problème, non je pense pas que SFML 2.1 y change grand chose. Encore une fois, regarde d'abord ton code avant de chercher l'erreur ailleurs...
Titre: Re : Bug avec les threads. (Les mutex ne marchent pas dans un certain cas précis.)
Posté par: Lolilolight le Août 08, 2013, 05:57:08 pm
Ok Laurent mais je ne vais pas mettre tout sur le dos de mon code source non plus.
Certains OS (je ne coterai pas lesquels.) sont connu pour buguer ou alors freeze à certains moment, je n'ai pas que ce problème avec mon code.

Mais aussi avec d'autres jeux.

De plus il me semble qu'il y a encore quelques bugs ou alors quelques bout de code trop lent avec la SFML, sinon, tu ne referais pas à chaque fois des nouvelles versions.



Titre: Re : Bug avec les threads. (Les mutex ne marchent pas dans un certain cas précis.)
Posté par: Laurent le Août 08, 2013, 06:20:46 pm
Citer
Ok Laurent mais je ne vais pas mettre tout sur le dos de mon code source non plus.
Si, c'est au contraire la plus saine des attitudes à avoir. Ce n'est qu'une fois que tu as debuggé à fond et que tu es certain que l'erreur vient d'ailleurs, que tu peux affirmer "c'est SFML / l'OS / xxx qui bug". Mais tant que tu n'es pas sûr à 100% de ton code, alors continue à le debugger.

Moi je dis ça pour toi : en rejetant systématiquement la faute sur SFML ou l'OS tu perds un temps considérable, puisque tu ne fais pas ce qu'il faut pour régler le problème (i.e. debugger ton code).
Titre: Re : Bug avec les threads. (Les mutex ne marchent pas dans un certain cas précis.)
Posté par: Lolilolight le Août 08, 2013, 06:51:44 pm
Ouais, aussi mais là j'ai regardé avec le profiler dans mon code et y'a rien qui semble suspect donc..., ce problème de freeze vient soit de la SFML ou de l'os.
Titre: Re : Re : Bug avec les threads. (Les mutex ne marchent pas dans un certain cas précis.)
Posté par: lefreut le Août 08, 2013, 09:22:04 pm
J'ai essayer de mettre des mutex.lock et unlock dans cette fonction mais ça ne résoud pas le problème.

Tu as un problème d'accès sur une zone mémoire invalide (à priori accès en dehors des bornes d'un tableau). Cela n'a rien à voir avec du multithreading, rajouter des mutex ne va rien changer.

Bon j'ai rajouté ça pour être sur que j ne sois pas plus petit que 0 non plus mais ça ne résous pas le crash, maintenant ça crash tout le temps que ça soit avec le débugueur ou pas. :o

while (j < children.size() && children[j]->isTraveled())
            j++;
        j--;
        j = (j < 0) ? 0 : j;
 

Si j est un unsigned int, il ne sera jamais négatif (0 - 1 en unsigned int va donner UINT_MAX). Utilise un int.

Au passage si children contient aucun élément, même avec j = 0 ce code est incorrect:
int distMin = children[j]->getCenter().computeDist(finalPos);
Titre: Re : Bug avec les threads. (Les mutex ne marchent pas dans un certain cas précis.)
Posté par: Lolilolight le Août 08, 2013, 09:50:01 pm
Salut, oui j'ai changé mon unsigned int en int et ça marche maintenant.  :)
Ca n'avais en effet rien à voir avec le multithreading. :/

children[0] contient toujours un élément dans mon cas donc pas de soucis de ce côté là.
Titre: Re : Bug avec les threads. (Les mutex ne marchent pas dans un certain cas précis.)
Posté par: Laurent le Août 08, 2013, 10:23:21 pm
T'as la tête dure hein... :-\
Titre: Re : Re : Bug avec les threads. (Les mutex ne marchent pas dans un certain cas p
Posté par: cobra.one le Août 08, 2013, 11:20:20 pm
ce problème de freeze vient soit de la SFML ou de l'os.

Tu leur diras ça à tes futurs utilisateurs s'il te rapportent un comportement inattendu... ?

Surtout qu'à chaque fois tu finis par découvrir que les bugs viennent de ton code et/ou n'impliquent pas les éléments que tu incriminais au départ.

Alors si tu es aussi sûr du reste de ton code que tu es sûr de ce que tu nous montres... avant d'y trouver des bugs, pas étonnants que tu ais des problèmes, qui à 99% ne viennent ni de SFML et encore moins de l'OS (à moins que tu n'utilisent des algos tellement poussés que tu lèverais à toi seul des bugs qui n'auraient pas été découvert par les millions d'utilisateurs qui utilisent cet OS quotidiennement).


Titre: Re : Bug avec les threads. (Les mutex ne marchent pas dans un certain cas précis.)
Posté par: Lolilolight le Août 09, 2013, 10:08:39 pm
1)Je parle de feeze, pas de bug là.
2)Me redemande pas de retrouver ou ça freeze, parce la programmation de bas niveau ce n'est pas mon fort, la programmation de haut niveau par contre si. :P (A part que faut juste que je me mette au débuguer parce que les bugs se situent souvent pas là ou je pense.)
Titre: Re : Bug avec les threads. (Les mutex ne marchent pas dans un certain cas précis.)
Posté par: cobra.one le Août 09, 2013, 11:29:55 pm
Oh bah alors si ça frise sans beuguer... tout va bien ! :D

Ce que j'aime c'est ton humilité... m'enfin peut-être as-tu une très solide expérience du développement "de haut niveau" qui te permet ces certitudes, moi tout ce que je sais c'est que si tu pars bille en tête qu'un comportement que tu observes mais ne comprends pas ne peut pas venir de ton code "tellement qu'il est bien pensé dès le départ", tu ne vas pas beaucoup progresser dans ton approche, et ton soft non plus ne risque pas d'évoluer.

Le design, les rapports, toussa c'est super, m'enfin avoir un minimum le nez dans la technique (le "bas niveau") c'est pas mal aussi, ça permet de comprendre certaines choses (pourquoi ça freeze alors qu'il y a sûrement moyen d'éviter ça par exemple), surtout quand on développe un jeu. Ca évite aussi de faire des gros bricolages tous moches pour contourner un problème parcequ'on ne le comprend pas.

Bref je m'éloigne fortement du sujet, je ne peux que te souhaiter de réussir à pondre un soft stable, maintenable et upgradable, les utilisateurs jugeront.

Une dernière anecdote pour la route des fois qu'un éclair de lucidité te traverserait l'esprit : l'autre jour, lors d'une recompilation du soft sur lequel je bosse, le compilo me sort une erreur chelou sur une formule de maths un peu compliquée... alors que syntaxiquement le code était bon. En fait c'était moi qui m'était planté sur une manip' lors de la build, et j'ai mis pas mal de temps à trouver l'erreur. A ma place t'aurais sûrement reporté un bug sur le bugtracker de GCC non ? Genre "Les priorités d'opérateurs ne fonctionnent pas dans certains cas"... ?

En tous cas bonne chance... :P
Titre: Re : Bug avec les threads. (Les mutex ne marchent pas dans un certain cas précis.)
Posté par: Lolilolight le Août 10, 2013, 01:07:51 pm
Bah comme débugueur j'ai connu mieux..., même si gdb n'est pas bugué, les erreurs sont parfois difficile à repérer.

Celle-ci en tout cas j'ai mis longtemps avant de trouver tout ça parce que j'avait la valeur INT_MAX et donc que je dépassait les limites de mon std::vector.

Hors que en java par exemple j'aurai eu un ArrayIndexOutOfBoundException bref...

Prochaine fois je me retiendrai de ne pas faire un post en disant que c'est un bug avec les thread hors que ce n'est pas le cas désolé.

PS : j'aimais bien le java auparavant et je pensais passé à un seul langage pour le site web et le mon soft mais j'ai changé d'avis par la suite car je me suis rendu compte que ça ne marchait pas vraiment toujours très bien, bref, en tout cas j'avais plus de difficulté avec JOGL que avec la SFML car problèmes d'accès coucurrents avec JOGL et problème aussi avec JEE.
(Bref plus de lacunes dans le domaine surement.)
Je ne peux malheureusement pas mélanger les outils des 2 langages. (gdb pour le c++ et le débugueur java sous éclipse.)
Tout du moins je pense pas, maintenant si y'a moyen de le faire je serai intéressé mdr.

PS : et puis bon je me suis rendu compte que les méthodes des librairies ne sont pas toujours thread safe ce qui parfois pose des problèmes, surtout quand la librairie utilise des threads en interne, bref, c'est ce qui s'appelle, la misère qu'on a avec les nouvelles technologie.
Titre: Re : Bug avec les threads. (Les mutex ne marchent pas dans un certain cas précis.)
Posté par: Laurent le Août 10, 2013, 03:25:05 pm
Note que SFML possède un binding Java, si tu préfères cet environnement.
Titre: Re : Bug avec les threads. (Les mutex ne marchent pas dans un certain cas précis.)
Posté par: Lolilolight le Août 10, 2013, 05:30:56 pm
Je ne tiens pas à recoder, plus de 50 fichiers en c++, en java. :/ (Mon jeux va encore contenir plus de fichier que ta bibliothéque vu qu'il y a mon propre framework qui englobe la SFML + le gameplay, et , quelques fichier SFML que j'ai modifié.)

Tu utilises JOGL pour le binding java ?

Je n'aime pas trop JOGL, elle utilise un thread en interne pour gérer l'affihage et ça m'a posé des problèmes d'accès concurrant avec d'autres composants java comme par exemple, les arraylist.

De plus je ne sais pas très bien comment fonctionne le système de gestion des accès concurrants en java avec wait() et notify() pour ça que je suis passé à la SFML avec les mutex qui sont largement plus simple à utilisé.

Maintenant si tu n'utilises pas JOGL j'aurai surement utilisé le binding java mais il n'existait pas encore je pense au moment ou j'ai commencé à passé au c++. (Celà fait maintenant déja depuis pas mal d'années.)
Titre: Re : Bug avec les threads. (Les mutex ne marchent pas dans un certain cas précis.)
Posté par: Laurent le Août 10, 2013, 07:13:51 pm
Citer
Tu utilises JOGL pour le binding java ?
Déjà ce n'est pas moi qui l'ai écrit. Ensuite non, c'est un binding donc tout ce qu'il utilise c'est SFML (C++). Un binding n'est pas une réécriture, c'est un wrapper par dessus la bibliothèque originale.

Citer
De plus je ne sais pas très bien comment fonctionne le système de gestion des accès concurrants en java avec wait() et notify() pour ça que je suis passé à la SFML avec les mutex qui sont largement plus simple à utilisé.
wait() + notify(), c'est le mécanisme qu'on nomme en général "condition" ou "variable de condition". C'est très différent des mutexs (complémentaire), et c'est intéressant / utile de savoir un peu ce que c'est et comment ça fonctionne. Même en C++ c'est très souvent utile.
Titre: Re : Bug avec les threads. (Les mutex ne marchent pas dans un certain cas précis.)
Posté par: Lolilolight le Août 10, 2013, 08:29:29 pm
Un warper, ok, alors il passe surement par un mécanisme qui permet d'insérer du code écrit en c++ dans du code java, je ne sais plus comment ça s'appelle. (Mais oui c'est vrai qu'il y a moyen.)
Bref je pourrai toujours apprendre à me servir des variables de condition, avec les thread du c++11 surement, avant de faire un binding java de mon framework.
Mais je suis pas un spécialiste je ne sais pas du tout quand c'est mieux d'utiliser les variables de condition, quand c'est mieux d'utiliser les mutex ou autre chose.

Mais java utilise bien des variables de condition.
Titre: Re : Bug avec les threads. (Les mutex ne marchent pas dans un certain cas précis.)
Posté par: Laurent le Août 10, 2013, 08:39:47 pm
Citer
Un warper, ok, alors il passe surement par un mécanisme qui permet d'insérer du code écrit en c++ dans du code java, je ne sais plus comment ça s'appelle.
JNI.
Titre: Re : Bug avec les threads. (Les mutex ne marchent pas dans un certain cas précis.)
Posté par: Lolilolight le Août 10, 2013, 10:10:51 pm
Bien que pour la 2D en java j'aurai peut être pas eu besoin de passer par la SFML, ça inclus déjà toute les classes 2D dont j'ai besoin.

J'ai regardé un article sur les thread en plus, il y a pas mal de trucs bien pour la syncchronisation :
Il y a aussi les mutex mais en plus les sémaphore, les variables de conditions, un Executor, etc...
Qui pourraient être intéressant si je décide un jour de passer en multithreading, et que je n'ai pas vraiment le choix au niveau de l'implémentation pour les accès concurrents mais bon pas encore sûr que j'aurai besoin d'autre primitives de synchronisation que les mutex, je vais essayer de faire un système de liste d'attente plutôt si un jour je décide de passé en multi-threading. (un thread pour update la liste de tiles et un autre thread pour les afficher.)
Je pensais faire une classe SceneUpdater avec un thread, et un genre de vector a 2 dimensions contenant les tiles à afficher et la position dans la file d'attente. (Je peux pas utiliser une std::map vu que ça ne stocke pas les informations dans l'ordre dans lequel on les insères, donc là c'est encore plus compliqué je suis obligé de faire un vector qui sotcke les ordres d'insertion, bref...)
Je trouverais bien un truc pour ma passer de toute ces complications inutiles. :)
Par contre y'a un endroit ou je sais pas faire sans mutex et ça m'embête un peut, c'est que, l'utilisateur changer de chemin, on ne peut pas changer chemin en même temps que l'autre thread update la position du personnage à partir de l'ancien chemin.
Et je pense que c'est là que ça freeze un peu.
Pas vraiment trouvé de manière de contourné un mutex pour ce là. :/

Et c'est là que ça freeze un peu. :/
Titre: Re : Bug avec les threads. (Les mutex ne marchent pas dans un certain cas précis.)
Posté par: Lolilolight le Août 10, 2013, 10:33:58 pm
Et puis on est jamais à l'abris des accès concurrents car même si on gère une liste d'attente, les thread pourront accèder à cette liste d'attente en même temps donc..., ça ne résoudrait pas le problème.

Je ne vois rien d'autre que d'utiliser autre chose qu'un mutex dans ce cas là, comme par exemple, la classe Executor en java qui exécute les actions dans l'ordre dans lequel elle sont ajoutée, et qui je pense est beaucoup plus optimisé qu'un mutex.

Le c++11 possède peut être un truc du genre, faudrait que je prenne le temps d'y jeter un coup d'oeuil, sinon, je repasserai surement au java.
Bref en gros ce style de code pour réduire les accès concurrent c'est pas à haut niveau que ça doit se faire,donc, pas dans mon code, c'est à plus bas niveau que ça se fait.
Titre: Re : Thread et mutex, comment bien les utiliser ?
Posté par: Lolilolight le Août 11, 2013, 07:49:14 am
Bon pour la seconde solution j'ai trouvé, plutôt que de verouiller le mutex à chaque tour de boucle, je vais faire ceci :

-Le personnage veut bouger : il vérifie si un déplacement est en cours, si oui, il demande à l'autre thread de verouiller le mutex  et attend que le mutex soit verrouillé avant de changer sa trajectoire, puis il demande à l'autre thread de déverouillé le mutex.

Par contre je vois pas trop comment faire un système multi-thread qui mets à jour et affiche les tiles, je voudrais faire en fait comme le fait Swing en java, en utilisant une liste blocante, voici le tutoriel en question qui explique à quoi ça ressemble (voir la fin ou il parle de l'exécutor.) : http://rom.developpez.com/java-synchronisation/ (http://rom.developpez.com/java-synchronisation/)

Mais là je vois pas encore trop bien comment implémenter ça.  :-\
Titre: Re : Bug avec les threads. (Les mutex ne marchent pas dans un certain cas précis.)
Posté par: Lolilolight le Août 11, 2013, 08:22:02 am
Bon ça va j'ai enfin trouvé mon bonheur : http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3562.pdf (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3562.pdf)

Donc go pour le c++11 qui me permettra de faire du code plus optimisé. :)

J'ai lu pas mal d'article et ça a l'air bien le c++11. :)

Bref le problème vient du fait que les thread de la sfml et les mutex ne sont plus suffisant pour ce que je veux faire si je veux passer en multi-thread. :/
Donc on peut dire que ce sujet est résolu. :)
Titre: Re : Comment bien utiliser les mutex ?
Posté par: cobra.one le Août 11, 2013, 12:15:26 pm
Mais la question c'est : as-tu réellement besoin de gérer tout un bric à brac de threads qui risque de tout compliquer sans te rendre réellement service par rapport à un système mono thread ?
Titre: Re : Comment bien utiliser les mutex ?
Posté par: Lolilolight le Août 11, 2013, 12:31:47 pm
Citer
Mais la question c'est : as-tu réellement besoin de gérer tout un bric à brac de threads qui risque de tout compliquer sans te rendre réellement service par rapport à un système mono thread ?

Heu peut être que j'en ai pas besoin mais se serait dommage de s'en passer sur un PC multi-coeur.

J'ai essayer d'utiliser une variable de condition avec les thread du c++11 pour verrouiller le mutex que quand le personnage change de trajectoire uniquement et donc pour verouiller seulement quand cela est nacessaire :

unique_lock<mutex> locker(server.getGLockModifyPath());
    //avoid spurious wakeup.
    while(!server.isGNotified()) {
        g_signal.wait(locker);
    }
Mise à jour de la position du personnage suivant sa trajectoire.
 
Changement de trajectoire.
               unique_lock<mutex> locker (server.getLockModifyPath());
               server.setGNotified(false);
               (*it).first->getCurrentCar()->setFightingMode(false);
               (*it).first->getCurrentCar()->setAttacking(false);
               (*it).first->getCurrentCar()->setFocusedMonster(NULL);
               vector<string> parts = split(message, "#");
               GridMap &gm = *World::getMap("Map test")->gridMap;
               Vec2f startPos (conversionStringInt(parts[0]), conversionStringInt(parts[1]));
               Vec2f finalPos (conversionStringInt(parts[2]), conversionStringInt(parts[3]));

               vector<Vec2f> positions = gm.getPath(startPos, finalPos);
               Caracter *car = (*it).first->getCurrentCar();
               car->setPath(positions);
               car->setCurrentPointIndex(0);
               Vec2f dir = (car->getPath()[1] - car->getCenter()).normalize();
               car->setDir(dir);
               car->setMoveFromKeyboard(false);
               car->setMoving(true);
               vector<Vec2f> path = car->getPath();
               response = "PPATH*"+conversionIntString(path.size())+"*";
               for (unsigned int i = 0; i < path.size(); i++) {
                    response += conversionIntString(path[i].x)+"*"+conversionIntString(path[i].y);
                    if (i != path.size() - 1)
                        response += "*";
               }
               packet<<response;
               (*it).first->sendTCPMessage(packet);
               server.setGNotified(true);
               //Fait appel à g_signal.notify_one()
               server.notify();
 
Mais ça ne résoud pas le problème, le problème vient parfois en plein milieu du déplacement et pas toujours quand je change de trajectoire donc, c'est quand je déplace ma vue côté client que ça bloque quelque part, et pas côté serveur, j'ai aussi se problème en monothread avec mon éditeur de map, déplacement de la vue lente parfois...
Titre: Ca tourne!!!
Posté par: Lolilolight le Août 11, 2013, 01:55:45 pm
Ca y est, ça tourne enfin!

En fait j'ai déclarer mon mutex en statique et je l'ai passé à mes classes plutôt que de faire un getter renvoyant une référence sur le mutex, car, apparemment faire comme ça c'est archi lent!

Bref merci au c++11, c'est tout simplement de la balle.  :)

Titre: Re : Re : Comment bien utiliser les mutex ?
Posté par: cobra.one le Août 11, 2013, 02:06:41 pm
Citer
Mais la question c'est : as-tu réellement besoin de gérer tout un bric à brac de threads qui risque de tout compliquer sans te rendre réellement service par rapport à un système mono thread ?

Heu peut être que j'en ai pas besoin mais se serait dommage de s'en passer sur un PC multi-coeur.

Hélas il ne suffit pas de créer quelques threads ça et là et de laisser le système se débrouiller avec pour que ça soit plus efficace qu'un seul thread qui réaliserait les mêmes opérations.
Titre: Re : Comment bien utiliser les mutex ?
Posté par: Lolilolight le Août 11, 2013, 03:05:27 pm
En effet bref heureusement que y'a le c++11 et d'autres librairies qui introduisent des primitives de synchronisation de plus haut niveau que le mutex qui permettent de gérer une liste d'attente sinon j'aurai galéré en effet. :/

Mais pour l'affichage et la mise à jour des tiles je pense que je vais laisser ça dans un seul thread vu que je galère déja assez comme ça. :/
Titre: Re : Comment bien utiliser les mutex ?
Posté par: Lolilolight le Août 11, 2013, 04:18:36 pm
Bien que à la limite je pourrai peut être maintenant, grâce à cet exemple de code source fournis par cet excellent lien : http://www.codeproject.com/Articles/598695/Cplusplus11-threads-locks-and-condition-variables (http://www.codeproject.com/Articles/598695/Cplusplus11-threads-locks-and-condition-variables)
La sfml ne suffirait pas pour faire ce genre de chose. (J'ai en effet un écran noir quand mon thread n'a pas fini d'ajouter les tiles visibles à l'écran dans le vecteur quand je déplace la vue du coup résultat incohérent et mon écran se met à clignoter.)
Il me faut donc utiliser une variable de condition, qui exécute le code d'affichage que si le vecteur de tiles est rempli.

C'est le même principe que le code source plus bas ou il a 2 thread, un qui ajoute les message d'erreur dans un vecteur et l'autre thread qui les affiche à l'écran.

Je pense que en adaptant mon code pour qu'il fasse la même chose avec mes tiles, (il me faudra juste un vecteur a 2 dimensions car j'affiche plusieurs tiles d'un coup et pas un message à la fois comme dans son exemple.) il doit y avoir moyen de faire ne sorte que ça soit plus éfficace qu'avec un seul thread.
Titre: Re : Comment bien utiliser les mutex ?
Posté par: Lolilolight 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 ?
Titre: Re : Comment bien utiliser les mutex ?
Posté par: Laurent 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.
Titre: Re : Comment bien utiliser les mutex ?
Posté par: Lolilolight 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     ?? () (??:??)
 
Titre: Re : Comment bien utiliser les mutex ?
Posté par: Laurent 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.
Titre: Re : Re : Comment bien utiliser les mutex ?
Posté par: cobra.one 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...
Titre: Re : Comment bien utiliser les mutex ?
Posté par: Lolilolight 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. :)
Titre: Re : Comment bien utiliser les mutex ?
Posté par: Lolilolight 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
Titre: Re : Comment bien utiliser les mutex ?
Posté par: Laurent le Août 12, 2013, 10:19:48 am
Citer
Il se passe des choses bizarre dans ce monde.
Dans ton code ;)
Titre: Re : Comment bien utiliser les mutex ?
Posté par: Lolilolight 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 ?
Titre: Re : Comment bien utiliser les mutex ?
Posté par: Laurent 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.
Titre: Re : Comment bien utiliser les mutex ?
Posté par: cobra.one 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
Titre: Re : Comment bien utiliser les mutex ?
Posté par: Lolilolight 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. :/
Titre: Re : Comment bien utiliser les mutex ?
Posté par: Laurent 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.
Titre: Re : Comment bien utiliser les mutex ?
Posté par: Lolilolight 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.
Titre: Re : Comment bien utiliser les mutex ?
Posté par: Laurent 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.
Titre: Re : Comment bien utiliser les mutex ?
Posté par: Lolilolight le Août 12, 2013, 06:33:29 pm
Ok je vais essayer de poster moins de messages et un peu plus de code. :X