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 :

Comment détruire un thread ?


Sujet :

Threads & Processus C++

  1. #1
    sas
    sas est déconnecté
    Membre émérite

    Profil pro
    Inscrit en
    Novembre 2003
    Messages
    54
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2003
    Messages : 54
    Par défaut Comment détruire un thread ?
    salut à tous,

    je voudrais implémenter ce mode de recherche dans un "annuaire" :

    quand l'utilisateur change un critère de recherche :
    -si un thread est lancé, on le détruit
    -lance un nouveau thread avec les nouveaux critères de recherche
    -n'attend pas la fin du thread

    le thread consiste à envoyer une requete de sélection à une base de donnée mysql, à récupérer dans un vecteur tampon le résultat, et à afficher dans une TreeView.

    ce qui me pose problème c'est la destruction du thread, j'utilise les threads de la Glibmm, avec une interface construit sur Gtkmm.

    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
     
        //  vide le contenu de la TreeView
        //  récupère les critères de sélection
     
        // si un thread est déjà lancé
        if (!_M_job_thread_ptr)
        {
             // on le détruit, mais comment ??
            _M_job_thread_ptr = NULL;
        }
     
        // création du nouveau thread
         _M_job_thread_ptr = Glib::Thread::create(sigc::mem_fun(this, &recherche_client::store_thread), true);
     
        // continue l'éxécution
        _M_job_thread_ptr->yield(); // est-ce la bonne méthode ?
    tel-quel, ce code fait planté l'application, sans utilisé un thread, le reste du code fonctionne mais "freeze" l'interface.

    une idée ??

  2. #2
    Membre chevronné
    Profil pro
    Inscrit en
    Novembre 2003
    Messages
    394
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2003
    Messages : 394
    Par défaut
    Je connais mal glibmm, mais après un bref coup d'oeil sur leur doc, il apparaît qu'un objet de type thread n'est pas destructible. En d'autre terme, il est impossible de brutalement interrompre une sous-tâche.

    Ce que tu peux faire néanmoins, c'est faire en sorte qu'un thread attende la fin d'un autre via un join(). Le tout après c'est de faire en sorte que la tâche que l'on attend s'interrompe au plus vite.
    Si cette sous tâche possède une boucle d'execution, alors pas de problème. Il suffit d'ajouter un booléen comme condition d'arrêt. Ce booléen sera positionné par la tâche qui attend (avant de se mettre en attente bien sûr). Ainsi la sous-tâche termine d'elle même.
    Si ce n'est pas le cas, alors soit un tel méchanisme peut-être mis en place, soit je ne vois pas d'autre solution que d'attendre que la première requête se termine.

  3. #3
    Expert confirmé

    Homme Profil pro
    pdg
    Inscrit en
    Juin 2003
    Messages
    5 756
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : pdg

    Informations forums :
    Inscription : Juin 2003
    Messages : 5 756
    Billets dans le blog
    3
    Par défaut
    La manière propre de faire c'est de demander au thread de d'arrêter (solution de VoidSeer avec booléen par exemple).
    Le problème quand tu tue le thread, c'est que tout ce qu'il aura alloué ne sera pas libéré : fuites de mémoire, lock base de données, etc...

  4. #4
    Membre chevronné
    Profil pro
    Inscrit en
    Novembre 2003
    Messages
    394
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2003
    Messages : 394
    Par défaut
    Ce problème de sécurité de terminaison est d'ailleurs, AMA, la raison pour laquelle la glibmm ne fournit pas cette fonctionnalité.

  5. #5
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 393
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 393
    Par défaut
    Attention toutefois si on joue avec les booléens: J'ai déja eu des problèmes avec à cause des optimisations: Ne pas oublier de déclarer le booléen en question en volatile...
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  6. #6
    sas
    sas est déconnecté
    Membre émérite

    Profil pro
    Inscrit en
    Novembre 2003
    Messages
    54
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2003
    Messages : 54
    Par défaut
    merci pour ces précisions.

    je vais coder la solution du flag, de plus en ayant fait quelques mesures, j'ai constaté que la boucle de remplissage du vecteur tampon est 10 fois plus longue que l'éxécution de la requête sql par le serveur (sans ces tests je croyais que c'était le contraire)

    Citation Envoyé par Médinoc
    Attention toutefois si on joue avec les booléens: J'ai déja eu des problèmes avec à cause des optimisations: Ne pas oublier de déclarer le booléen en question en volatile...
    peux-tu préciser??

  7. #7
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 393
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 393
    Par défaut
    http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclang/html/_langref_volatile.asp
    Citation Envoyé par MSDN
    can be modified in the program by something such as the operating system, the hardware, or a concurrently executing thread
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  8. #8
    Membre chevronné
    Profil pro
    Inscrit en
    Novembre 2003
    Messages
    394
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2003
    Messages : 394
    Par défaut
    Lorsqu'une variable peut être modifiée autrement que par une instruction à l'intérieur d'un bloc (si elle est modifiée par une autre tâche dans ce cas), elle doit être déclarée comme volatile.
    Cela implique, qu'à chaque fois qu'elle est utilisée, le compilateur fera en sorte que sa valeur soit toujours cherchée en mémoire et n'appliquera aucune optimisation.
    Dans ton cas, par exemple le compilateur pourrait analyser que la valeur du flag n'est jamais modifiée dans la boucle et donc la charger une fois pour tout le bloc englobant.

    Il suffit juste de rajouter le mot-clef volatile devant la définition de la variable.

  9. #9
    sas
    sas est déconnecté
    Membre émérite

    Profil pro
    Inscrit en
    Novembre 2003
    Messages
    54
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2003
    Messages : 54
    Par défaut
    je ne vois pas trop comment adapter cette méthode car quand l'utilisateur change un critère de recherche ça correspond à :

    si le contenu d'une Gtk::Entry est changé, éxécuté une fonction mais tout pendant que la fonction n'est pas éxécuté, l'utilisateur n'a plus la main....

    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
     
    {
        // quelque part dans lors de la création des Widgets
        nom_entry->signal_changed().connect(SigC::slot(*this, &recherche_client::do_update));    
    }
     
     
    recherche_client::do_update()
    {
        //  vide le contenu de la TreeView
        //  récupère les critères de sélection
     
        // création du nouveau thread
        _M_job_thread_ptr = Glib::Thread::create(sigc::mem_fun(this, &recherche_client::store_thread), true);
        _M_job_thread_ptr->join();
    }

  10. #10
    Expert confirmé
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 292
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2003
    Messages : 5 292
    Par défaut
    volatile est le truc au sujet duquel personne n'est d'accord (je parle des gurus, pas de nous) sur le fonctionnement et l'utilité.
    Je crois que Loïc avait posté des liens au sujet de ce mot clé contreversé.
    Blog|FAQ C++|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS|Bons livres sur le C++
    Les MP ne sont pas une hotline. Je ne réponds à aucune question technique par le biais de ce média. Et de toutes façons, ma BAL sur dvpz est pleine...

  11. #11
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 393
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 393
    Par défaut
    Ben, c'est vrai qu'un booléen volatile peut souvent être remplacé par un objet de synchronisation système (ici, un event)...

    Mais lorsqu'on ne fait PAS une attente active (ici, on n'en fait pas), lequel est le plus performant ?
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  12. #12
    Expert confirmé

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Par défaut
    Citation Envoyé par VoidSeer
    Il suffit juste de rajouter le mot-clef volatile devant la définition de la variable.
    Les choses sont quand même plus compliquées que cela. volatile a été inventé pour accéder aux registres de controles des E/S. Toute autre utilisation est loin d'être sure. Et comme les accès à ces registres sont maintenant protégés par les S.E., quasiment toutes les utilisations de volatiles en dehors des S.E. sont douteuses.

    En particulier, dans le contexte multi-thread, volatile n'arrange pas grand chose même s'il évitera bien quelques problèmes avec les optimiseurs. Il n'impose pas un accès atomique (autrement dit une thread peut voir quelque chose qui n'est ni l'ancienne valeur, ni la nouvelle) ni un ordre relatif des écritures: on peut voir la nouvelle valeur d'une valeur et l'ancienne valeur d'une autre variable volatile qui pourtant avait été modifiée avant. Les problèmes seront naturellement rares et n'arriveront vraissemblablement que dans des vraies configurations multiprocesseurs -- je crois que les processeurs à coeurs multiples partagent ou synchronisent leurs caches suffisemment pour les éviter.

    La vraie solution ne nécessite pas volatile, mais l'utilisation des barrières mémoires -- et d'un compilateur sachant leurs effets sinon les optimisations peuvent poser des problèmes. Le moyen le plus simple d'avoir ces barrières c'est d'utiliser les méthodes de synchronisation de thread fournies par l'OS (mutex, ...).

  13. #13
    Expert confirmé

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Par défaut
    Citation Envoyé par Luc Hermitte
    volatile est le truc au sujet duquel personne n'est d'accord (je parle des gurus, pas de nous) sur le fonctionnement et l'utilité.
    Je crois que Loïc avait posté des liens au sujet de ce mot clé contreversé.
    Je crois que les experts sont d'accord sur la situation de volatile. Ce sur quoi ils ne sont pas d'accord c'est son avenir (le laisser tel quel, le virer complètement ou en faire quelque chose d'utile au niveau applicatif, par exemple qu'un accès à une variable volatile implique des barrières mémoire).

  14. #14
    Expert confirmé

    Homme Profil pro
    pdg
    Inscrit en
    Juin 2003
    Messages
    5 756
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : pdg

    Informations forums :
    Inscription : Juin 2003
    Messages : 5 756
    Billets dans le blog
    3
    Par défaut
    Le C++ pur n'a pas de notion de thread, donc ce n'est pas du côté du langage qu'il faut chercher une solution viable.
    volatile est justifié dans le cas de setjmp etc... il me semble.

  15. #15
    Expert confirmé

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Par défaut
    Citation Envoyé par Aurelien.Regat-Barrel
    volatile est justifié dans le cas de setjmp etc
    Je ne vois pas a quoi le etc fait allusion.

    Le seul effet a ma connaissance decrit precisement par la norme de volatile est en effet que les variables volatiles sont les seules dont la valeur est garantie au retour d'un setjmp par un longjmp.

  16. #16
    Expert confirmé

    Homme Profil pro
    pdg
    Inscrit en
    Juin 2003
    Messages
    5 756
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : pdg

    Informations forums :
    Inscription : Juin 2003
    Messages : 5 756
    Billets dans le blog
    3
    Par défaut
    Citation Envoyé par jmarc68
    Je ne vois pas a quoi le etc fait allusion.
    Au principe du jump (setjmp/longjmp).

  17. #17
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 393
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 393
    Par défaut
    Citation Envoyé par jmarc68
    Le seul effet a ma connaissance decrit precisement par la norme de volatile est en effet que les variables volatiles sont les seules dont la valeur est garantie au retour d'un setjmp par un longjmp.
    Là, c'est moi qui ne comprends plus rien...

    "La valeur est garantie" dans quel sens?
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  18. #18
    Expert confirmé

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Par défaut
    Citation Envoyé par Médinoc
    Citation Envoyé par jmarc68
    Le seul effet a ma connaissance decrit precisement par la norme de volatile est en effet que les variables volatiles sont les seules dont la valeur est garantie au retour d'un setjmp par un longjmp.
    Là, c'est moi qui ne comprends plus rien...

    "La valeur est garantie" dans quel sens?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    jmp_buf env;
    switch (setjmp(env)) {
       case 0:
             x = 5;
             fonction_ne_modifiant_pas_x(); // mais retournant eventuellement par longjmp
             break;
       case 1:
             assert(x == 5); // peut echouer si x n'est pas volatile
     }
    Mais bon, setjmp et longjmp interagissant tres mal avec les destructeurs, il vaut mieux les oublier en C++.

  19. #19
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 393
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 393
    Par défaut
    Merci, j'ai compris pour setjmp/volatile...
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  20. #20
    sas
    sas est déconnecté
    Membre émérite

    Profil pro
    Inscrit en
    Novembre 2003
    Messages
    54
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2003
    Messages : 54
    Par défaut
    après pas mal d'essais, j'ai finallement écrit un code qui fonctionne voici en gros la mécanisme :

    il me reste quelques tests à faire pour voir sa solidité.

    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
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
     
    {
         // quelques part quand je crée les widgets
         // émet un signal dès que l'un des critères change
     
        nom_entry->signal_changed().connect(SigC::slot(*this, &recherche_client::do_update));
        prenom_entry->signal_changed().connect(SigC::slot(*this, &recherche_client::do_update));
        adresse_entry->signal_changed().connect(SigC::slot(*this, &recherche_client::do_update));
        code_postal_entry->signal_changed().connect(SigC::slot(*this, &recherche_client::do_update));
        (ville_comboboxentrytext->get_entry())->signal_changed().connect(SigC::slot(*this, &recherche_client::do_update));
    }
     
    void
    recherche_client::do_update()
    {
        try {
            Glib::Thread * search_thread_ptr = NULL;
     
            // ici on récupère les critères
     
            if (_M_search_started)  // si un thread de recherche est lancé
            {
                Glib::Thread * wait_thread_ptr = Glib::Thread::create(sigc::mem_fun(this, &recherche_client::wait_thread), true);
                wait_thread_ptr->join(); 
            }
     
            // vide le contenu de la treeview
            _M_refListStore->clear();
     
            _M_search_finished = false;
     
            // lance le thread de recherche sans attendre la fin de son éxécution
            search_thread_ptr = Glib::Thread::create(sigc::mem_fun(this, &recherche_client::store_thread), true);
            if (search_thread_ptr != NULL)
            {
                _M_search_started = true;
            }
        }
        catch (CEngineException &e)
        {
           exception_dialog dialog(e);
           dialog.run();
        }
    }
     
    void
    recherche_client::wait_thread()
    {
        // indique à la fonction de recherche d'arréter la boucle
        // de remplissage du tampon
        CEngine::Instance().stop_search();
     
        //  permet de sortir de la boucle d'affichage de la treeview
        _M_search_complete = false;
     
        {
            Glib::Mutex::Lock lock (mutex_);
     
            while (!_M_search_finished)
                _M_cond_search_finished_.wait(mutex_);
        }    
    }
     
    void
    recherche_client::store_thread()       
    {
        CClientList client_list;
     
       {
            Glib::Mutex::Lock lock (mutex_);
     
            CEngine::Instance().rechercheClient(_M_client_search, client_list);
            _M_search_complete = CEngine::Instance().is_search_complete();
     
            if ((client_list.size() > 0) && (_M_search_complete))
            {
                 CClientList_Const_Iterator it;
                 Gtk::TreeModel::Row row;
     
                 for (it = client_list.begin(); it != client_list.end(); it++)
                 {
                     // ici on met à jour la treeview
     
                     if (!_M_search_complete) break;
                 }
            }
     
            _M_search_started = false;
            _M_search_finished = true;
     
            _M_cond_search_finished_.signal();      
        }
    }
    j'ai défini les booléens suivants :
    _M_search_started, _M_search_finished, _M_search_complete ainsi que celui représenté par CEngine::Instance().stop_search() et CEngine::Instance().is_search_complete() (c'est le même)

    en volatile puis en 'normal', dans les deux cas ça n'a rien changé sur le résultat (aucun crash, aucune erreur de résultat)

Discussions similaires

  1. [Threads] Comment terminer un thread ?
    Par Wookai dans le forum Concurrence et multi-thread
    Réponses: 5
    Dernier message: 16/04/2005, 13h25
  2. Réponses: 18
    Dernier message: 06/04/2005, 14h09
  3. Réponses: 3
    Dernier message: 08/01/2005, 10h01
  4. [Thread] comment arreter un thread qui execute une methode b
    Par Cyber@l dans le forum Concurrence et multi-thread
    Réponses: 8
    Dernier message: 04/08/2004, 10h51
  5. comment stoper 1 thread d'arrière-plan
    Par ms91fr dans le forum Langage
    Réponses: 3
    Dernier message: 06/06/2003, 17h46

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