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

C++ Discussion :

Design pour arrêter des traitements en environnement multithread


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Octobre 2010
    Messages
    14
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2010
    Messages : 14
    Par défaut Design pour arrêter des traitements en environnement multithread
    Salut,

    Je suis entrain de travailler sur un design pour permettre d'arrêter proprement l'execution de traitement (fonctions de calculs),
    suite au declenchement d'une alerte dans un ou plusieurs threads quelquonque.
    La seule solution que je vois c'est de checker un booléen partout ou je pourrai dans l'execution des fonctions ( technique utilisé aussi pour les annulations )
    quelqu'un a t-il déja employé d'autres techniques plus propres ? ou une version améliorée ?

    J'ai mis le code que je viens d'écrire pour illustrer mon propos...
    j'utilise la bibliothèque boost pour synchronisé les threads.

    ps :
    les threads d'alertes invoqueront la méthode cManager::Alert_all() pour arrêter tout...

    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
    class cFunction;
     
    class cManager
    {
    public :
    	void Alert_All();
    protected :
    	void AddFunction(boost::shared_ptr<cFunction>);
    	void RemoveFunction(boost::shared_ptr<cFunction>);
    private:
    	std::vector<boost::shared_ptr<cFunction> > p_Running;
    };
     
    void cManager::Alert_All()
    {
    	for (size_t i = 0 ; i < p_Running.size(); i++ )
    	{
    		p_Running[i]->set_alert(true);
    	}
    }
     
    class cFunction
    {
    	bool p_alert;
    	boost::mutex p_lock;
     
    public:
    	cFunction();
    	void set_alert(const bool& alert_);
    	bool get_alert();
    	void execution();
    	void alert_clean();
    };
     
     
    void cFunction::execution()
    {
    	// faire des traitements
    	for (unsigned int i = 0; i < 1000; i++)
    	{
    		if (!get_alert())
    		{
    			// traitement boucle
    		}
    	}
     
    	if (!get_alert())
    	{
    		// traitement singulier
    	}
     
    	if (get_alert())
    	{
    		alert_clean();
    	}
    }
     
    cFunction::cFunction() : p_alert(false)
    {
    }
     
    void cFunction::set_alert( const bool& alert_ )
    {
    	boost::mutex::scoped_lock guard(p_lock);
    	p_alert = alert_;
    }
     
    bool cFunction::get_alert()
    {
    	boost::mutex::scoped_lock guard(p_lock);
    	return p_alert;
    }
     
    void cFunction::alert_clean()
    {
    	// opérations pour terminer correctement la fonction
     
    	set_alert(false);
    }

  2. #2
    Membre chevronné Avatar de seeme
    Profil pro
    Inscrit en
    Octobre 2005
    Messages
    430
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France

    Informations forums :
    Inscription : Octobre 2005
    Messages : 430
    Par défaut
    Bonjour!

    Pourquoi ne pas plutôt utiliser des signaux ou des sémaphores? Ca m'aurait paru plus adaptés non?

  3. #3
    Membre averti
    Profil pro
    Inscrit en
    Octobre 2010
    Messages
    14
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2010
    Messages : 14
    Par défaut
    des signaux boost ne sont pas thread safe.
    j'utiliserai boost.asio pour notifier.

    les semaphores, peux tu t'expliquer ?

  4. #4
    Membre chevronné Avatar de seeme
    Profil pro
    Inscrit en
    Octobre 2005
    Messages
    430
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France

    Informations forums :
    Inscription : Octobre 2005
    Messages : 430
    Par défaut
    Autant pour moi, les sémaphore ne sont pas vraiment indiqué pour ça, je me suis laissé emporté.. (dès que je vois "thread", dans matête ça fait "tilt: sémaphore"... )

    Donc désolé pour mon intervention ^^

  5. #5
    Membre Expert
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    1 415
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mars 2007
    Messages : 1 415
    Par défaut
    Citation Envoyé par seeme Voir le message
    Autant pour moi, les sémaphore ne sont pas vraiment indiqué pour ça, je me suis laissé emporté.. (dès que je vois "thread", dans matête ça fait "tilt: sémaphore"... )
    Non ce n'est pas si idiot, un sémaphore pourrait être utilisé pour protéger le booléen qui est une ressource commune.

    Mais bon ça reste bourrin comme technique, avec tous les risques d'interblocages qui vont avec, etc...

  6. #6
    Membre averti
    Profil pro
    Inscrit en
    Octobre 2010
    Messages
    14
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2010
    Messages : 14
    Par défaut
    Citation Envoyé par jblecanard Voir le message
    Non ce n'est pas si idiot, un sémaphore pourrait être utilisé pour protéger le booléen qui est une ressource commune.

    Mais bon ça reste bourrin comme technique, avec tous les risques d'interblocages qui vont avec, etc...
    hmm oui j'y pense avec une wait condition sur le booléen.

    Je ne suis pas le seul à coder, dois-je obliger les développeurs à checker partout ou ils peuvent dans le code de leurs fonctions ? c'est étrange comme "archi"
    il y' a pas un système de points d'annulation qui existe pour les threads ?

  7. #7
    screetch
    Invité(e)
    Par défaut
    j'ai eu un peu le même problème mais chez moi le design est (beaucoup) plus complexe.
    Les threads executent des taches dépendantes les unes des autres et il n'est pas possible d'interrompre une tâche en cours. Lorsqu'il n'y a plus de tâches, les threads sont libérés.

    Ici le problème serait que ta méthode "execute" fait trop de choses et son design est très rigide:
    si tu ajoutes de nouvelles phases ou en retire, le code de cette fonction doit être réexaminé et l'utilisation du signal pourrait être cassée.

    Tu pourrais (si ca vaut le coup) généraliser en divisant en sous-tâches qui sont ajoutées dans une liste au tout début. Ensuite a chauqe tour de boucle, on vérifie si le signal est mis. Je vois donc ca comme:
    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
    void cFunction::execution()
    {
        prepare(); //peut être dans le constructeur plutot?
        while (!get_alert() && Task* task = mTaskList.pop())
        {
            task->execute();
        }
        if (get_alert())
        {
            alert_clean();
        }
    }
     
    void cFunction::prepare()
    {
        for (unsigned int i = 0; i < 1000; i++)
        {
            mTaskList.push(new TraitementBoucle(i));
        }
        mTaskList.push(new TraitementSingulier);
    }
    A NOTER que cette facon de faire, bien que plus souple, est beaucoup plus gourmande en ressources (mémoire et CPU, puisqu'il faut allouer toute les tâches et les stocker). A n'utiliser que si tu en as vraiment besoin.
    Il est aussi possible d'optimiser si execute() renvoie la tâche suivante, dans ce cas tu ne stockes pas de liste mais execute() renvoie (et peut-être crée sur demande) la tâche qui devrait être éxecutée ensuite.
    Dans ton cas tu peux avoir une tâche Head qui va automatiquemet te renvoyer une tâche TraitementBoucle, qui se renvoie elle-même 1000 fois puis renvoie une tâche TraitementSingulier, etc etc etc
    enfin tout ca c'est de même, seulement si tu en as besoin.

  8. #8
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Salut,
    Citation Envoyé par ICE Tea Voir le message
    des signaux boost ne sont pas thread safe.
    j'utiliserai boost.asio pour notifier.
    boost::signals2, qui remplace boost::signal dans les "dernières" versions (>= 1.35, me semble-t-il) sont thread safe.

    Cela vaudrait la peine d'être approfondi, non
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  9. #9
    Membre averti
    Profil pro
    Inscrit en
    Octobre 2010
    Messages
    14
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2010
    Messages : 14
    Par défaut
    Citation Envoyé par koala01 Voir le message
    Salut,
    boost::signals2, qui remplace boost::signal dans les "dernières" versions (>= 1.35, me semble-t-il) sont thread safe.

    Cela vaudrait la peine d'être approfondi, non
    J' avais étudié la question, disons que boost.signal2 est thread safe lors de l'association du signal et du slot ( connect / disconnect).
    Par contre le concept de "Safe Cross-Thread Signals"
    ( i.e émission d'un signal qui déclenche de façon safe des slots dans des threads différents) n'est pas supporté à ma connaissance

    tu confirmes n'est ce pas ?
    As tu une parade ?

    ps : Le seul qui répond à ce besoin d'après mes recherches c'est QT signal/slot mais je n'aime pas QT car c'est trop intrusif...

  10. #10
    Membre expérimenté Avatar de Nogane
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    241
    Détails du profil
    Informations personnelles :
    Âge : 45
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 241
    Par défaut
    Bonjour,
    Il y as dans les threads de boost un système de point d'interruption:
    http://www.boost.org/doc/libs/1_45_0...anagement.html

    En gros, quand on demande l'arrêt d'un thread, le prochain point d'interuption rencontré par le thread lancera une exception de type boost::thread_interrupted, ce qui arrêtera proprement le thread.

    Par contre il est nécessaire:
    - De rajouter des points d'interruption(ex : boost::this_thread::interruption_point() ) aux endroits stratégiques.
    - D'avoir du code exception-safe

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

Discussions similaires

  1. Les design pattern pour créer des jeux
    Par alex6891 dans le forum Design Patterns
    Réponses: 4
    Dernier message: 26/11/2018, 19h59
  2. Réponses: 4
    Dernier message: 14/06/2010, 21h18
  3. [W98] Un équivalent au gestionnaire des tâches (pour arrêter des processus)
    Par annedeblois dans le forum Windows 2000/Me/98/95
    Réponses: 2
    Dernier message: 28/09/2007, 17h36
  4. Aide pour définir des index (traitement long)
    Par m-mas dans le forum MS SQL Server
    Réponses: 7
    Dernier message: 25/05/2006, 20h39
  5. Réponses: 11
    Dernier message: 03/11/2005, 17h59

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