Partage
  • Partager sur Facebook
  • Partager sur Twitter

Thread dans une classe, fonction membre et arg

    14 mai 2019 à 23:08:28

    Bonsoir,

    je créer un sujet pour un problème assez particulier, j'ai débuté le c++ en autodidacte il y a un petit moment avec le site openclassroom mais j'ai pu constaté que je dois réapprendre pas mal de choses par rapport au contenu du site qui me semble un peu dépassé...
    Notamment là j'ai besoin d'en apprendre plus sur les threads (qui n'est pas au menu du cours sauf erreur de ma part), pour résumer la situation, je code un jeu en sfml avec un map interactive.

    J'ai un main dans lequel je déclare une tilemap, vers la fin du main je fais appel à une fonction membre de ma classe tilemap, à savoir drawingEngine.

    Dans cette fonction membre je déclare un thread de la fonction suivante

    thread t1(floodFill, currentTile.x, currentTile.y, tiles, ref(fstVector));

    La fonction floodFill est une fonction disponible dans ma classe tilemap :

        vector<int> TileMap::floodFill(int x, int y, int* tiles, vector<int>& vctr)
        {
    
            if(tiles[x + y * m_width] == 0)
            {
                vctr.push_back(x + y * m_width);
                floodFill((x+1), y, tiles, vctr);
                floodFill(x, (y+1), tiles, vctr);
                floodFill((x-1), y, tiles, vctr);
                floodFill(x, (y-1), tiles, vctr);
            }
    
            return vctr;
        }

    Malheuresement, c'est ce qui m'amène ici, j'ai une erreur de compilation et j'arrive pas à comprendre mon erreur parce que je suis pas assez documenté sur le sujet, ce qui m'amène à vous demander deux choses.

    La première, est-ce que vous auriez un site à me conseiller qui explique bien en détail les threads (anglais/français/japonais ya pas de soucis) ?
    La deuxième, est-ce que vous pourriez me dire ce qui ne marche pas dans mon code ? :lol:

    Désolé je suis pas habitué à poster ici je suis pas encore familier avec toutes les règles désolé si je fais une bourde et merci d'avance pour ceux qui veulent bien m'aider :)


    • Partager sur Facebook
    • Partager sur Twitter
      14 mai 2019 à 23:57:52

      Basiquement un thread est une fonction qui va s'executer en parallele de ton code principal.

      Par contre la parallellisation vient avec un côut processeur non négligeable, et des contraintes d'accessibilité des variables:
      Tu dois t'assurer que les variables communes à ton thread et le programme principale ne sont pas accédées en même temps, sinon cela produit des resultat imprévisibles (undefined behavior, ou UB), les mutex sont la pour gérer cette problematique.

      Concernant ton code, je ne suis pas convaincu que les appels récursifs vont avoir l'effet escomptés:

      if(tiles[x + y * m_width] == 0)    // donc x et y sont a zéro ?
      {
          vctr.push_back(x + y * m_width);
          floodFill((x+1), y, tiles, vctr);    // n'ajoute rien, x+1 est different de zero
          floodFill(x, (y+1), tiles, vctr);    // n'ajoute rien, y+1 est different de zero.
          floodFill((x-1), y, tiles, vctr);    // n'ajoute rien, x-1 est different de zero.
          floodFill(x, (y-1), tiles, vctr);    // n'ajoute rien, y-1 est different de zero.
      }

      Inutile de retourner vctr vu qu'il est passé par référence non constante.
      Il sert a quoi tiles ?

      -
      Edité par Deedolith 14 mai 2019 à 23:58:27

      • Partager sur Facebook
      • Partager sur Twitter
        15 mai 2019 à 9:02:06

        Lu'!

        ZeonSoldier a écrit:

        Malheuresement, c'est ce qui m'amène ici, j'ai une erreur de compilation et j'arrive pas à comprendre mon erreur parce que je suis pas assez documenté sur le sujet, ce qui m'amène à vous demander deux choses.

        [...]

        Désolé je suis pas habitué à poster ici je suis pas encore familier avec toutes les règles désolé si je fais une bourde et merci d'avance pour ceux qui veulent bien m'aider :)

        Bonne habitude à prendre pour poster : donner le message d'erreur parce que l'on a pas tout ton code sous la main donc on ne va pas pouvoir deviner le message. Au pifomètre je dirais que c'est la référence qui pèche dans le cas d'un passage à un thread.

        Sinon la vraie question : es tu sûr d'avoir besoin de multithreading ?

        • Partager sur Facebook
        • Partager sur Twitter

        Posez vos questions ou discutez informatique, sur le Discord NaN | Tuto : Preuve de programmes C

          15 mai 2019 à 11:24:42

          Merci pour ces réponses, p

          remière chose, j'avais zappé le message d'erreur, il est là, par contre il est énorme :lol:

          C:\Program Files (x86)\CodeBlocks\MinGW\lib\gcc\mingw32\5.1.0\include\c++\functional||In instantiation of 'struct std::_Bind_check_arity<std::vector<int> (TileMap::*)(int, int, int*, std::vector<int>&), int&, int&, int*&, std::reference_wrapper<std::vector<int, std::allocator<int> > > >':|
          C:\Program Files (x86)\CodeBlocks\MinGW\lib\gcc\mingw32\5.1.0\include\c++\functional|1538|required from 'struct std::_Bind_simple_helper<std::vector<int> (TileMap::*)(int, int, int*, std::vector<int>&), int&, int&, int*&, std::reference_wrapper<std::vector<int, std::allocator<int> > > >'|
          C:\Program Files (x86)\CodeBlocks\MinGW\lib\gcc\mingw32\5.1.0\include\c++\functional|1552|  required by substitution of 'template<class _Callable, class ... _Args> typename std::_Bind_simple_helper<_Func, _BoundArgs>::__type std::__bind_simple(_Callable&&, _Args&& ...) [with _Callable = std::vector<int> (TileMap::*)(int, int, int*, std::vector<int>&); _Args = {int&, int&, int*&, std::reference_wrapper<std::vector<int, std::allocator<int> > >}]'|
          C:\Program Files (x86)\CodeBlocks\MinGW\lib\gcc\mingw32\5.1.0\include\c++\thread|142|required from 'std::thread::thread(_Callable&&, _Args&& ...) [with _Callable = std::vector<int> (TileMap::*)(int, int, int*, std::vector<int>&); _Args = {int&, int&, int*&, std::reference_wrapper<std::vector<int, std::allocator<int> > >}]'|
          D:\Programmation\C++\Game\TileMap.cpp|227|required from here|
          C:\Program Files (x86)\CodeBlocks\MinGW\lib\gcc\mingw32\5.1.0\include\c++\functional|1426|error: static assertion failed: Wrong number of arguments for pointer-to-member|
          C:\Program Files (x86)\CodeBlocks\MinGW\lib\gcc\mingw32\5.1.0\include\c++\functional||In instantiation of 'struct std::_Bind_simple<std::_Mem_fn<std::vector<int> (TileMap::*)(int, int, int*, std::vector<int>&)>(int, int, int*, std::reference_wrapper<std::vector<int> >)>':|
          C:\Program Files (x86)\CodeBlocks\MinGW\lib\gcc\mingw32\5.1.0\include\c++\thread|142|required from 'std::thread::thread(_Callable&&, _Args&& ...) [with _Callable = std::vector<int> (TileMap::*)(int, int, int*, std::vector<int>&); _Args = {int&, int&, int*&, std::reference_wrapper<std::vector<int, std::allocator<int> > >}]'|
          D:\Programmation\C++\Game\TileMap.cpp|227|required from here|
          C:\Program Files (x86)\CodeBlocks\MinGW\lib\gcc\mingw32\5.1.0\include\c++\functional|1505|error: no type named 'type' in 'class std::result_of<std::_Mem_fn<std::vector<int> (TileMap::*)(int, int, int*, std::vector<int>&)>(int, int, int*, std::reference_wrapper<std::vector<int> >)>'|
          C:\Program Files (x86)\CodeBlocks\MinGW\lib\gcc\mingw32\5.1.0\include\c++\functional|1526|error: no type named 'type' in 'class std::result_of<std::_Mem_fn<std::vector<int> (TileMap::*)(int, int, int*, std::vector<int>&)>(int, int, int*, std::reference_wrapper<std::vector<int> >)>'|

          Deedolith, je vais check les mutex dès aujourd'hui.
          Pour la ligne

          if(tiles[x + y * m_width] == 0)

          En fait c'est une tilemap, ma map est un tableau de int et cette ligne me permet de vérifier si la valeur de la tile est égale à zéro :)
          Pour le return bien vu, je viens d'apprendre std::ref() mais j'avais pas encore changé ça :s

          • Partager sur Facebook
          • Partager sur Twitter
            15 mai 2019 à 17:30:58

            Avec un pointeur de fonction membre, il faut une instance. Où est l'instance de TileMap dans la construction du thread ? (Voir la cppreference.com pour sont utilisation). Seconde chose, pourquoi floodFill est une fonction membre non statique alors qu'elle ne fait aucunement référence à ses membres ?

            Je trouve ta fonction particulièrement étrange, pour moi il y a une boucle infinie.

            Au passage, tu n'as pas répondu à la question de Ksass'Peuk: es tu sûr d'avoir besoin de multithreading ?

            -
            Edité par jo_link_noir 15 mai 2019 à 17:34:00

            • Partager sur Facebook
            • Partager sur Twitter
              15 mai 2019 à 19:51:07

              Pour l'instance de TileMap, c'est une question que je me posais, la déclaration du thread se trouve dans une fonction membre, du coup je ne peux pas déclarer l'instance :s

              Maintenant pour les fonctions statiques/non statiques, c'est parce que je ne suis pas encore arriver là, il me reste deux chapitres, quelque chose comme ça à propos de la POO :(

              La boucle n'est pas infinie puisque la fonction va à un moment donné rencontrer une tile dont la valeur n'est pas 0.

              Ah désolé pour l'oubli, alors j'en ai besoin parce que j'utilise la librairie SFML pour coder un petit jeu et c'est nécessaire pour que je continue à rafraîchir ma fenêtre :/

              Edit : j'ai essayé la syntaxe suivante :

              thread t1(TileMap::floodFill(currentTile.x, currentTile.y, tiles, ref(fstVector)));

              Ce qui a diminué le message d'erreur lors de la compilation :)


              ||=== Build: Debug in Game (compiler: GNU GCC Compiler) ===|
              C:\Program Files (x86)\CodeBlocks\MinGW\lib\gcc\mingw32\5.1.0\include\c++\functional||In instantiation of 'struct std::_Bind_simple<std::vector<int>()>':|
              C:\Program Files (x86)\CodeBlocks\MinGW\lib\gcc\mingw32\5.1.0\include\c++\thread|142|required from 'std::thread::thread(_Callable&&, _Args&& ...) [with _Callable = std::vector<int>; _Args = {}]'|
              D:\Programmation\C++\Game\TileMap.cpp|228|required from here|
              C:\Program Files (x86)\CodeBlocks\MinGW\lib\gcc\mingw32\5.1.0\include\c++\functional|1505|error: no type named 'type' in 'class std::result_of<std::vector<int>()>'|
              C:\Program Files (x86)\CodeBlocks\MinGW\lib\gcc\mingw32\5.1.0\include\c++\functional|1526|error: no type named 'type' in 'class std::result_of<std::vector<int>()>'|
              ||=== Build failed: 2 error(s), 3 warning(s) (0 minute(s), 0 second(s)) ===|

              -
              Edité par ZeonSoldier 15 mai 2019 à 19:57:11

              • Partager sur Facebook
              • Partager sur Twitter
                15 mai 2019 à 19:52:55

                ZeonSoldier a écrit:

                Ah désolé pour l'oubli, alors j'en ai besoin parce que j'utilise la librairie SFML pour coder un petit jeu et c'est nécessaire pour que je continue à rafraîchir ma fenêtre :/

                Non ce n'est pas nécessaire :) . Il est peu probable que ton ordinateur ne soit pas assez rapide pour faire :

                • récupération des événements,
                • préparation des données,
                • préparation des éléments graphiques,
                • affichage (et retour à l'étape 1).
                • Partager sur Facebook
                • Partager sur Twitter

                Posez vos questions ou discutez informatique, sur le Discord NaN | Tuto : Preuve de programmes C

                  15 mai 2019 à 21:05:27

                  Justement c'est après avoir fait sans, constaté l'erreur et avoir demandé sur le forum de la SFML qu'on m'a dit ça, me voilà donc ici :)
                  • Partager sur Facebook
                  • Partager sur Twitter
                    15 mai 2019 à 21:45:21

                    Salut,

                    Je comprends ton problème.

                    Je te déconseille de partir sur du multithreading. Le résultat obtenu risque d'être décevant car ton programme risque de se finir beaucoup plus vite que prévu. Ta grille (ou peu importe la zone que tu essaies de remplir) va se remplir en un temps assez court et surtout tu ne pourras pas contrôler ce temps. :-°

                    Personnellement, je te conseille de partir sur la deuxième solution que t'as proposé Laurent (le créateur de la SFML, au passage ;)), c'est à dire de coder ta fonction floodFill() de façon à ce que tu puisses avancer le remplissage par incréments. A mon avis, ça serait beaucoup plus simple (bien que moins élégant), d'oublier la récursivité pour ce cas là.

                    Je sais pas sûr d'avoir été très clair, hésite pas à demander si t'as pas compris ;)

                    • Partager sur Facebook
                    • Partager sur Twitter
                      15 mai 2019 à 23:18:55

                      Franchement, le multithreading dans un jeux est entre autre utilisé pour présenter à l'utilisateur un joli écran animé (bar de progression par exemple) pour faire patienter pendant le chargement des (très) nombreuses ressources (fonts / textures / modeles 3D ect ….)

                      Dans le cadre d'un "petit" jeux où les ressources sont peut nombreuses, le temps de chargement de ces dernières n'est pas important (voir négligeable), donc la necessité d'un ecran de chargement est caduque.

                      Fait d'abord sans, occupe toi du jeux en lui même, le chargement des ressources pourra toujours être amélioré plus tard.

                      PS:
                      using namespace, c'est le MAAAAAAALLLLL
                      (je suis sûr que tu l'as utilisé).

                      • Partager sur Facebook
                      • Partager sur Twitter
                        16 mai 2019 à 10:42:13

                        D'accord je vais essayer de faire comme au pire je reviens vers toi par mp si j'ai un soucis Raynobrak :)

                        Ah d'accord c'est compris pour le multithreading :D


                        Pour le using namespace, je l'utilise parce que c'était dans le cours openclassroom, je me rends compte petit à petit qu'il a l'air bien désuet et que pas mal de monde le pointe du doigt :lol:
                        Du coup c'est quoi le soucis avec using namespace ?
                        • Partager sur Facebook
                        • Partager sur Twitter
                          16 mai 2019 à 10:53:37

                          ZeonSoldier a écrit:

                          Pour le using namespace, je l'utilise parce que c'était dans le cours openclassroom, je me rends compte petit à petit (1) qu'il a l'air bien désuet et que pas mal de monde le pointe du doigt.
                          (2) Du coup c'est quoi le soucis avec using namespace ?

                          (1) Il était même déjà pas franchement glorieux quand il était pas encore obsolète. L'obsolescence de ce cours c'est la partie émergée de l'iceberg. Il y a quasiment tout qui va pas dedans.

                          (2) Ici.

                          • Partager sur Facebook
                          • Partager sur Twitter

                          Posez vos questions ou discutez informatique, sur le Discord NaN | Tuto : Preuve de programmes C

                            16 mai 2019 à 12:46:02

                            Ah d'accord, j'aurais peut être dû apprendre le c++ ailleurs finalement :lol:

                            -
                            Edité par ZeonSoldier 16 mai 2019 à 12:53:56

                            • Partager sur Facebook
                            • Partager sur Twitter

                            Thread dans une classe, fonction membre et arg

                            × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                            × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                            • Editeur
                            • Markdown