Forum de la communauté SFML

Aide => Système => Discussion démarrée par: Lolilolight le Juillet 02, 2012, 03:04:47 pm

Titre: [RESOLU]Plantage au niveau des threads.
Posté par: Lolilolight le Juillet 02, 2012, 03:04:47 pm
Salut!

Alors je m'explique j'essaye d'afficher des animations et de les supprimer dans mon éditeur, j'ai d'abord essayer de le faire sans utiliser un thread et la ça marche :

    vector<Anim*> anims = map->gridMap->getAnims();
    for (int i = 0; i < anims.size(); i++) {
        if (anims[i]->isRunning() && anims[i]->getElapsedTime() > anims[i]->getFrameRate()) {
            Tile *prev = anims[i]->getCurrentTile();
            anims[i]->nextImage();
            Tile *newTile = anims[i]->getCurrentTile();
            Vec2f centerView (centerView.x, centerView.y);
            map->gridMap->changeAnimTile(centerView, prev, newTile);
            anims[i]->resetClock();
        }
    }
 

Mes animations comme toutes mes tiles sont ajouté dans une grille virtuelle pour des question d'optimisation, bref voici la méthode qui les efface :

void GridMap::removeAnim (Anim *anim) {

    Vec2f tCorners[4];
    Vec2f position (anim->getPosition().x, anim->getPosition().y);
    Vec2f center (anim->getCenter().x, anim->getCenter().y);
    tCorners[0] = Vec2f (position.x - center.x, position.y - center.y);
    tCorners[1] = Vec2f (position.x + center.x, position.y - center.y);
    tCorners[2] = Vec2f (position.x - center.x, position.y + center.y);
    tCorners[3] = Vec2f (position.x + center.x, position.y + center.y);
    int s = sizeof(tCorners) / sizeof (Vec2f);
    for (int i = 0; i < s; i++) {

        CellMap *cellMap = getGridCellAt(tCorners[i]);
        if (cellMap != NULL) {
           cellMap->removeEntity(anim, anim->getZOrder());
           if (!cellMap->isEntityInside())
                removeCellMap(cellMap);
        }
    }
}
 

Après j'ai essayer de changer les tiles des animations avec un thread, donc j'ai créer une classe qui hérite de thread et j'ai mis le code dans la méthode run :

void AnimListener::Run () {
    while (running) {
        globalMutex.Lock();
        vector<Anim*> anims = canvas->getMap().gridMap->getAnims ();
        for (int i = 0; i < anims.size(); i++) {

            if (anims[i]->isRunning() && anims[i]->getElapsedTime() > anims[i]->getFrameRate()) {
                Tile *prev = anims[i]->getCurrentTile();
                anims[i]->nextImage();
                Tile *newTile = anims[i]->getCurrentTile();
                Vec2f centerView (canvas->getCenterView().x, canvas->getCenterView().y);
                canvas->getMap().gridMap->changeAnimTile(centerView, prev, newTile);
                anims[i]->resetClock();
            }
        }
        globalMutex.Unlock();
    }
}
 
Malheureusement l'application plante et se termine en renvoyant comme erreur un std::bad_alloc dès que je veux effacer une animation.

Il m'indique que ça plante à cet endroit :

vector<Anim*> GridMap::getAnims () {
    vector<Anim*> allAnims;
    for (int i = 0; i < casesMap.size(); i++) {
        CellMap *cell = casesMap[i];
        for (int l = 0; l < 20; l++) {

            for (int n = 0; n < [s][color=red]cell->getEntitiesInside()[l].size()[/color][/s]; n++) {
                 if (cell->getEntityInside(n, l)->getType() == Entity::E_ANIMATION) {
                    bool contains = false;
                    for (int k = 0; k < allAnims.size(); k++) {
                        if (allAnims[k] == cell->getEntityInside(n, l))
                            contains = true;
                    }
                    if (!contains) {

                        allAnims.push_back(dynamic_cast<Anim*>(cell->getEntityInside(n, l)));
                    }
                 }

            }
        }

    }
    return allAnims;
}
 

Il me renvoie a la méthode size de la classe vector :
 size() const
      { return size_type(this->_M_impl._M_finish - this->_M_impl._M_start); }
 

Et je ne trouves pas l'erreur. =/ (que j'essaye avec ou sans Mutex cela plante. =/)

Merci d'avance pour votre aide.
Titre: Re : Plantage au niveau des threads.
Posté par: Laurent le Juillet 02, 2012, 03:37:06 pm
Sûrement un problème d'accès concurrent. Mais là avec tout ce code c'est difficile à voir. Cependant je vois que tu as un mutex à un seul endroit, alors que logiquement il devrait y avoir deux parties verrouillées (à moins que tu ne montres pas tout).

Sinon essaye de degrossir le code, là c'est assez indigeste on n'arrive pas trop à se concentrer sur le vrai problème. Si tu arrivais à écrire un code minimal qui reproduit le problème mais sans ton code original avec lagestion de map etc. ce serait top.
Titre: Re : Plantage au niveau des threads.
Posté par: Lolilolight le Juillet 02, 2012, 03:45:11 pm
Oui un problème d'accès concurrent je ne vois que ça.

Au niveau du code, je vais voir pour essayer d'en faire un plus simple, et de tester..., parce que j'avoue que je débute un peut dans se domaine avec se système de mutex.

Edit : Bah je viens de déclarer mon mutex dans le main et le passer à mes 2 classes, en faisant des appelle à Lock et Unlock dans mes 2 fonctions. (celle qui efface l'animation et l'autre qui change les tiles des animations.) et ça marche.

J'avais en effet fait une bêtise, je n'avais pas bien regarder le tutoriel du coup j'ai utiliser le mutex uniquement dans un seul thread..., merci Laurent maintenant ça marche.  :D
Titre: Re : Plantage au niveau des threads.
Posté par: Lolilolight le Juillet 03, 2012, 10:00:09 am
Bon bah j'ai trouvé le problème technique. :)
Donc je passe le sujet en résolu.