Partage
  • Partager sur Facebook
  • Partager sur Twitter

C++ instancier un thread dans le constructeur

    27 janvier 2019 à 19:16:07

    Bonjour à tous
    Je souhaite créer une classe qui crée un nouveau thread à chaque instanciation
    Le thread doit être crée lors de l'instanciation de l'objet, donc dans le constructeur ou dans une méthode appelée par le constructeur.
    Voici le code que j'ai réalisé sans succès
    Si quelqu'un peut m'aider ?
    #include <iostream>
    #include <thread>
    #include <unistd.h> //
    
    using namespace std;
    
    /////////////////////////////////////////////////
    class TESTT
    {
    public:
      TESTT();
      void ecrit(int);
    
    private:
        //static void* TH_sortie( void *arguments ); // methode appelee par le thread
        void TH_sortie(); // methode appelee par le thread
        thread mon_thread();
        int sortie;                         // attribut a afficher
    };
    //////////////////////////////////////////////////
    //Methodes de la classe TESTT
    //////////////////////////////////////////////////
    TESTT::TESTT()
    {
        mon_thread(TESTT::TH_sortie);
        mon_thread.join();
    }
    
    void TESTT::ecrit(int i)
    {
       cout<<"sortie = "<<i<<endl;
       sortie=i;
    }
    
    //void* TESTT::TH_sortie( void *arguments )
    void TESTT::TH_sortie()
    {
        while(1) {
        cout<<"Thread appele"<<endl;
     //   cout<<getId()<<endl;
     //   cout<<sortie<<endl;
        usleep(999999);
        }
    }
    
    ////////////// PP ////////////////////////////////////////
    
    int main (void)
    {
    int n=0,m=0;
     TESTT th1;
     TESTT th2;
     while(1)
      {
        th1.ecrit(n);
        th2.ecrit(m);
        n++;
        m--;
        usleep(500000);
      }
      return 0 ;
    }
    

    -
    Edité par cdupaty 28 janvier 2019 à 18:18:54

    • Partager sur Facebook
    • Partager sur Twitter
      28 janvier 2019 à 9:26:08

      Salut,

      Dans les règles du forum que tu as lues, il y a écrit comment poster du code correctement.

      • Alors déjà, je comprends pas pourquoi tu utilises un void* en C++. Il n'y a aucune raison de le faire.
      • Tu déclares mon_thread comme une fonction, je ne suis pas sûr que c'est ce que tu voulais. Et pour réaffecter un thread tu peux tout simplement faire =. C'est déplaçable.
      mon_thread = std::thread([this] () {
          TH_sortie();
      });
      • Partager sur Facebook
      • Partager sur Twitter

      git is great because Linus did it, mercurial is better because he didn't.

        28 janvier 2019 à 12:28:03

        Bonjour et merci pour la réponse

        J'ai corrigé la déclaration de mon_thread et crée le thread dans le constructeur avec le code proposé.
        J'ai 'enfin) une compilation sans erreur.

        Cependant le programme plante à l’exécution

        Voici le code

        #include <iostream>
        #include <thread>
        #include <unistd.h> //
        
        using namespace std;
        
        /////////////////////////////////////////////////
        class TESTT
        {
        public:
          TESTT();
          void ecrit(int);
        
        private:
            //static void* TH_sortie( void *arguments ); // methode appelee par le thread
            static void TH_sortie(void); // methode appelee par le thread
            thread mon_thread;
            int sortie;                         // attribut a afficher
        };
        //////////////////////////////////////////////////
        //Methodes de la classe TESTT
        //////////////////////////////////////////////////
        TESTT::TESTT()
        {
            thread mon_thread(TESTT::TH_sortie);
            mon_thread = thread([this] () { TH_sortie();
                                            });
            mon_thread.join();
        }
        
        void TESTT::ecrit(int i)
        {
           cout<<"sortie = "<<i<<endl;
           sortie=i;
        }
        
        //void* TESTT::TH_sortie( void *arguments )
        void TESTT::TH_sortie()
        {
            while(1) {
            thread::id mon_id = this_thread::get_id();
            cout<<"Thread appele -> "<<mon_id<<endl;
        
            //cout<<sortie<<endl;
            usleep(999999);
            }
        }
        
        ////////////// PP ////////////////////////////////////////
        
        int main (void)
        {
        int n=0,m=0;
         TESTT th1;
         TESTT th2;
         while(1)
          {
            th1.ecrit(n);
            th2.ecrit(m);
        	n++;
        	m--;
        	usleep(500000);
          }
          return 0 ;
        }
        

        Et voici le message d'erreur

        tTerminate called without an active exception
        hread appele -> Thread appele -> 32

        Thread appele -> Thread appele -> 23

        Process returned 3 (0x3)   execution time : 4.117 s
        Press any key to continue.

        D'après mes recherches, cela proviendrait d'un thread non détaché... Mais je veux une exécution périodique des threads. Je ne comprends pas le problème



        • Partager sur Facebook
        • Partager sur Twitter
          28 janvier 2019 à 13:50:47

          Normal, tu as oublié de join les threads.

          Il te faut une fonction pour stopper les threads et appeler join (mon_thread.join()) dessus.

          Le plus simple est de ne pas faire une boucle infinie while (1) mais une boucle du style :

          void TESTT::TH_sortie()
          {
              while (!jesus_returns_) {
                  // code actuel
              }
          }
          
          void TESTT::stop()
          {
              jesus_returns_ = true;
              mon_thread.join();
          }

          Où jesus_returns_ est une variable de type std::atomic<bool>. Ensuite tu peux faire stop() dans ton main tu peux appeler stop.

          • Partager sur Facebook
          • Partager sur Twitter

          git is great because Linus did it, mercurial is better because he didn't.

            28 janvier 2019 à 14:35:51

            Merci Markand, mais cela ne résout pas mon problème.

            Je travaille sur Raspberry , je cherche à créer une class qui gère une étiquette de quatre afficheurs 7 segments.
            Dans main on met à jour un simple tableau de quatre entiers
            Dans un thread actif toutes les 10mS environ, les afficheurs sont multiplexés et mis à jour.
            Le thread ne doit jamais s'arrêter, et être "invisible" dans le main.

            Voici ce que j'ai commencé à faire avant de me heurter au pb de la création d'un thread dans le constructeur.
            J'ai d'abord utilisé pthread, puis j'ai découvert thread en C++11, ou la création de thread est plus simple (me semble t il)

            Ca marche très bien en C : https://photos.app.goo.gl/JGz5Ddad6idYaNQ9A

            Le main :

            #include <stdio.h>
            #include "wiringPi.h"
            #include "etiq7seg.h"
            
            #define sega 17
            #define segb 22
            #define segc 19
            #define segd 6
            #define sege 5
            #define segf 27
            #define segg 26
            #define segdp 13
            #define cat1 12
            #define cat2 16
            #define cat3 20
            #define cat4 21
            
            
            
            int main (void)
            {
            int n=0;
             wiringPiSetupGpio () ;
             ETIQ7SEG aff7(sega,segb,segc,segd,sege,segf,segg,segdp,cat1,cat2,cat3,cat4);
             while(1)
              {
            	printf("%d\n",n);
                aff7.ecrit(n);
            	delay(100);
            	n++;
              }
              return 0 ;
            }
            
            

            Le .h

            #ifndef ETIQ7SEG_H
            #define ETIQ7SEG_H
            
            //#include <pthread.h>
            #include <thread>
            
            class ETIQ7SEG
            {
            public:
            
              ETIQ7SEG(int a, int b, int c, int d, int e, int f, int g, int dp, int c1, int c2, int c3, int c4);
              ~ETIQ7SEG();
              int ecrit(int);
            
            private:
                void aff7seg(int aff,int n);
            
            static void PI_thread( void ); thread mon_thread;
            int aff[4]; // 4 nombres a afficher int anoA,anoB,anoC,anoD,anoE,anoF,anoG,anoDP,catho1,catho2,catho3,catho4; // config materiel }; #endif




            -
            Edité par cdupaty 28 janvier 2019 à 18:25:02

            • Partager sur Facebook
            • Partager sur Twitter
              31 janvier 2019 à 8:42:24

              Bonjour à tous

              Pas de nouvelle... Je pense que mon problème de création de thread dans le constructeur n'est pas solutionnable.

              C'est dommage

              Merci encore

              • Partager sur Facebook
              • Partager sur Twitter
                31 janvier 2019 à 10:41:57

                En même temps, tu déclares une autre variable du même nom que ta variable membre dans ton constructeur.

                C'est pourtant simple.

                TESTT::TESTT()
                    : m_thread([this] () { TH_sortie(); })
                {
                }

                Mais comme dit, il te faut une fonction pour faire un .join() avant que ton programme s'arrête.

                • Partager sur Facebook
                • Partager sur Twitter

                git is great because Linus did it, mercurial is better because he didn't.

                C++ instancier un thread dans le constructeur

                × 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