IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Threads & Processus C++ Discussion :

Interaction entre thread et une classe


Sujet :

Threads & Processus C++

  1. #1
    Membre régulier
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Février 2013
    Messages
    84
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Février 2013
    Messages : 84
    Points : 94
    Points
    94
    Par défaut Interaction entre thread et une classe
    Bonjour,

    Je débute sur l'utilisation des threads en c++. J'ai fait un petit exemple pour illustrer ce que je souhaite faire :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
     
    #include <thread>
    #include <iostream>
    #include <chrono>
    #include <future>
     
    class A
    {
    	public:
    		A()
    		{
    			futureExit = exitSignal.get_future();
    		}
     
    		void launch()
    		{
    			m_thread = std::thread(&A::doWork, futureExit, std::ref(this));
    			std::this_thread::sleep_for(std::chrono::seconds(30));
    			exitSignal.set_value();
    			m_thread.join();
    		}
     
    		void function1()
    		{
    			std::cout << "function1" << std::endl;
    			my_variable++;
    		}
     
    		static void doWork(std::future<void> futureExit, A &oA)
    		{
    			std::cout << "doWork Start" << std::endl;
     
    			while (futureExit.wait_for(std::chrono::milliseconds(1)) == std::future_status::timeout)
    			{
    				std::cout << "Work..." << std::endl;
    				oA.function1();
    				oA.my_variable2++;
    				std::this_thread::sleep_for(std::chrono::milliseconds(1000));
    			}
     
    			std::cout << "doWork End" << std::endl;
    		}
     
    		int my_variable2;
     
    	private:
    		std::thread m_thread;
    		std::promise<void> exitSignal;
    		std::future<void> futureExit;
     
    		int my_variable;
    };
     
    int main()
    {
    	A oA;
    	oA.launch();
     
    	return 0;
    }
    J'ai une thread qui travaille et qui a besoin de modifier des variables ou d'appeler des fonctions de la classe A. Avant je n'utilisai pas std::ref et je me suis rendu compte que je travaillai sur une copie de la classe A. Donc les changements dans le thread n'étaient pas visible dans la classe A.

    Depuis que j'utilise std::ref, je n'arrive pas à compiler car j'utilise une fonction supprimée.

    Avez-vous des conseilles ou des idées d'amélioration du code.

    Merci d'avance

    PS : Je suis en C++11

  2. #2
    Expert éminent
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Décembre 2015
    Messages
    1 565
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Décembre 2015
    Messages : 1 565
    Points : 7 648
    Points
    7 648
    Par défaut
    Bonjour,

    Ce n'est pas this qu'il faut passer par référence mais c'est *this.
    Et la future elle aussi ne peut pas être passée par valeur, elle est dans this c'est inutile de la passer, sinon on pourrait aussi utiliser la référence.

  3. #3
    Membre éprouvé
    Avatar de Garvelienn
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Septembre 2016
    Messages
    244
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Septembre 2016
    Messages : 244
    Points : 993
    Points
    993
    Par défaut
    dalfab a raison. Par soucis pédagogique, je me permet d'expliquer un peu plus, si vous ne m'en voulez pas, dalfab

    this est un pointeur sur l'instance de la classe. Ainsi, dans votre code, vous passez la référence d'un pointeur d'une instance de la classe. Ce n'est pas une erreur en soit mais vous ne l'utilisez pas comme une référence de pointeur ensuite : d'où votre erreur à la compilation. En donnant *this, vous passeriez en paramètre une référence de l'instance de la classe. * permettant d'accéder à ce que pointe le pointeur (ici une instance de la classe).

    Pour la future, dalfab a déjà tout dit.
    «Le management, tel qu’on l’apprend dans les écoles et tel qu’on l’applique ensuite, sous prétexte de «motivation du personnel», organise exactement le contraire, à savoir la démotivation organisée.» - Bernard Stiegler

  4. #4
    Membre régulier
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Février 2013
    Messages
    84
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Février 2013
    Messages : 84
    Points : 94
    Points
    94
    Par défaut
    Merci de vos réponses.

    Une autre petite question concernant la création d'une thread :
    Est-il possible de passer "this" en utilisant la fonction pthread_create

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    ptrhead_t m_thread;
    pthread_create(&m_thread, NULL, A::doWork, (void*)&this);

  5. #5
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 115
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 115
    Points : 32 967
    Points
    32 967
    Billets dans le blog
    4
    Par défaut
    C'est bien entendu possible vu que pthread_create demande un void*.
    Et this est un T*, donc déjà un pointeur.
    Mais je trouve ça un peu dommage d'utiliser pthread quand std::thread est similaire et disponible.

    Enfin std::thread n'est pas utilisé correctement, ou plutôt de manière un peu absurde et sur-complexe.
    m_thread = std::thread(&A::doWork, futureExit, std::ref(this)); pourrait et devrait s'écrire tout simplement m_thread = std::thread([this](){ DoWork(); });
    Sinon si c'est pour faire un sleep suivi d'un join directement, le thread me semble des plus inutiles.
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  6. #6
    Membre régulier
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Février 2013
    Messages
    84
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Février 2013
    Messages : 84
    Points : 94
    Points
    94
    Par défaut
    Citation Envoyé par Bousk Voir le message
    Sinon si c'est pour faire un sleep suivi d'un join directement, le thread me semble des plus inutiles.
    Le code que j'ai mis me sert de test e ce n'est pas le code final. Mon but est de faire une thread de réception dans le cas d'une application client/server.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    pthread_create(&m_thread, NULL, A::doWork, (void*)&this);
    Quand j'utilise cette ligne de code j'ai une erreur à la compilation.

  7. #7
    Membre éprouvé
    Avatar de Garvelienn
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Septembre 2016
    Messages
    244
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Septembre 2016
    Messages : 244
    Points : 993
    Points
    993
    Par défaut
    Citation Envoyé par Guillaume1701 Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    pthread_create(&m_thread, NULL, A::doWork, (void*)&this);
    Quand j'utilise cette ligne de code j'ai une erreur à la compilation.
    Car vous faites encore la même erreur que dans le premier post. Je vous laisse chercher par rapport à ce qui a été dit précédemment.

    La doc : http://man7.org/linux/man-pages/man3..._create.3.html
    «Le management, tel qu’on l’apprend dans les écoles et tel qu’on l’applique ensuite, sous prétexte de «motivation du personnel», organise exactement le contraire, à savoir la démotivation organisée.» - Bernard Stiegler

  8. #8
    Membre régulier
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Février 2013
    Messages
    84
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Février 2013
    Messages : 84
    Points : 94
    Points
    94
    Par défaut
    Citation Envoyé par Garvelienn Voir le message
    Car vous faites encore la même erreur que dans le premier post. Je vous laisse chercher par rapport à ce qui a été dit précédemment.

    La doc : http://man7.org/linux/man-pages/man3..._create.3.html
    Oui effectivement, j'ai encore fait la même erreur. Cependant avec la ligne suivante :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    pthread_create(&(m_thread), NULL, &A::doWork, *this)
    J'ai l'erreur :

    Invalid conversion from 'void (*)(A&)' to 'void* (*)(void*)'
    Cannot convert 'A' to 'void*'

    Je commence à être un peu perdu là.

  9. #9
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 189
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 189
    Points : 17 141
    Points
    17 141
    Par défaut
    do_work n'est pas une fonction statique de A

    Essaie donc pthread_create(&(m_thread), NULL, [this](){doWork()}, NULL).
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
    • La plus sotte des questions est celle qu'on ne pose pas.
    Pour faire des graphes, essayez yEd.
    le ter nel est le titre porté par un de mes personnages de jeu de rôle

  10. #10
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 115
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 115
    Points : 32 967
    Points
    32 967
    Billets dans le blog
    4
    Par défaut
    Ça ne marchera pas, [this](){doWork()} ne peut pas être converti en void* (*)(void*) requis par pthread à cause de la capture.
    La syntaxe est pthread_create(&m_thread, NULL, &A::doWork, this); avec A::doWork déclarée comme static void* doWork(void*).
    Aisément trouvable à peu près partout sur internet
    http://lmgtfy.com/?q=pthread_create+example+c%2B%2B
    http://man7.org/linux/man-pages/man3..._create.3.html
    https://gist.github.com/fffaraz/83a1a133f1d257a6a98f
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  11. #11
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 189
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 189
    Points : 17 141
    Points
    17 141
    Par défaut
    Et pthread_create(&(m_thread), NULL, [this](void* a){ return this->doWork(a);}, NULL) ?

    Cela dit, la bonne réponse est probablement de rendre doWork static.

    La raison profonde, c'est qu'une fonction membre non static n'est appelable que sur une donnée de sa classe.
    Un pointeur de fonction membre d'une classe n'a pas la même forme qu'un pointeur de fonction libre (ou une fonction membre static).
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
    • La plus sotte des questions est celle qu'on ne pose pas.
    Pour faire des graphes, essayez yEd.
    le ter nel est le titre porté par un de mes personnages de jeu de rôle

  12. #12
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 115
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 115
    Points : 32 967
    Points
    32 967
    Billets dans le blog
    4
    Par défaut
    Tu as toujours une capture et donc la conversion est toujours impossible.
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Interaction entre thread principal et thread secondaire
    Par mehdi_me85 dans le forum Threads & Processus
    Réponses: 37
    Dernier message: 28/05/2009, 15h08
  2. Réponses: 5
    Dernier message: 29/01/2008, 19h22
  3. Thread dans une classe
    Par superpok dans le forum C#
    Réponses: 8
    Dernier message: 22/08/2007, 02h20
  4. thread dédié à une classe pour lui "donner vie"
    Par Dje14 dans le forum Threads & Processus
    Réponses: 5
    Dernier message: 02/06/2005, 16h46
  5. Thread dans une classe ?
    Par Sephi dans le forum Threads & Processus
    Réponses: 7
    Dernier message: 07/03/2004, 18h16

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo