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

Boost C++ Discussion :

Boost::thread : utilité de certaines classes ?


Sujet :

Boost C++

  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Août 2007
    Messages
    39
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2007
    Messages : 39
    Par défaut Boost::thread : utilité de certaines classes ?
    Salut à tous,
    Je suis en train de plancher sur la bibliothèque de gestion de threads de Boost, et j'ai une question à laquelle je ne parviens pas à répondre :
    Quelle est l'utilité des classes lock_guard, unique_lock, upgrade_lock et compagnie ?

    De ce j'ai compris, il suffit d'instantier un boost::mutex, boost::timed_mutex, boost::shared_mutex, etc. en fonction de ses besoin et de faire appel à lock() et unlock() (ou lock_shared(), etc.). Ca marche très bien comme ça, j'ai essayé avec des centaines de threads en même temps sur plusieurs ressources partagées, et les concepts de propriété exclusive, partagée, upgradable, etc. sont toujours respectés.

    Donc du coup, je comprends pas pourquoi on irait s'embêter à instantier un objet boost::lock_guard ou autre pour locker ces mutexs, je vois pas ce que cela apporte en plus.
    Est-ce que j'aurais loupé quelque chose ?
    Merci ^^

  2. #2
    Membre éclairé

    Profil pro
    Inscrit en
    Avril 2010
    Messages
    356
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2010
    Messages : 356
    Par défaut
    Je pense que scope_lock permet de gérer le problème des exceptions (comme les pointeurs intelligents pour les delete). Après, c'est le seul lock dont je me serve donc...

  3. #3
    Membre averti
    Profil pro
    Inscrit en
    Août 2007
    Messages
    39
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2007
    Messages : 39
    Par défaut
    Salut,
    Merci pour ta réponse,
    Il me semble (d'après la documentation de l'API) que scope_lock est un typedef de unique_lock <> avec le type de mutex utilisé (mutex, shared_mutex, etc.) comme paramètre du template. Donc ça m'intéresse, puisque ce qui m'intéresse ce sont les classes définies ici : lock_guard, unique_lock, shared_lock, etc.
    En quoi cela aide-t-elle donc par rapport aux risques d'exceptions ?
    Sinon, je pense qu'il me manque une compréhension générale de l'utilité de ces classes, par rapport à MUTEX.lock(), MUTEX.unlock(), etc.
    Merci !

  4. #4
    gl
    gl est déconnecté
    Rédacteur

    Homme Profil pro
    Inscrit en
    Juin 2002
    Messages
    2 165
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Juin 2002
    Messages : 2 165
    Par défaut
    Si ma mémoire est bonne, ce sont des enveloppes RAII pour les mutex.

    Citation Envoyé par ehmicky Voir le message
    En quoi cela aide-t-elle donc par rapport aux risques d'exceptions ?
    Sinon, je pense qu'il me manque une compréhension générale de l'utilité de ces classes, par rapport à MUTEX.lock(), MUTEX.unlock(), etc.
    Si la fonction lève une exception avant le unlock() du mutex, soit celui reste locked (si qui est probablement une erreur), soit tu dois te débrouiller à gérer le cas avec la main ce qui est fastidieux et source d'erreur.
    Alors qu'en cas d'exception, les variables locales sont détruites proprement. Dans le cas d'objet lock, le destructeur appel unlock() sur le mutex correspondant. Le mutex est donc bien libéré en cas d'exception sans avoir à le gérer soi-même (il est d'ailleurs également libéré lors de la sortie normale de la fonction, sans appel explicite à unlock).

  5. #5
    Membre averti
    Profil pro
    Inscrit en
    Août 2007
    Messages
    39
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2007
    Messages : 39
    Par défaut
    Salut,
    Merci, ok j'ai compris ! En gros : utiliser de tels classes, et non les fonctions MUTEX.lock(), etc., car ces dernières ne sont pas exception-safe

    J'en profite pour poser une seconde question liée, mais n'étant pas la question originale, si vous le voulez bien :
    J'ai déjà manipulé les threads via Glibc, puis SFML, maintenant je pense que Boost est une des meilleurs solutions en la matière (interopérable, efficace, extensible, etc.). A chaque fois, je sais pas trop comment me dépatouiller avec la portée des mes mutexs. Je leur donne une portée globale, pour qu'ils soient partagés par tous les threads, mais il me semble qu'il s'agisse d'une mauvaise pratique. Je me disais donc qu'il fallait peut-être construire une classe gérant tous les mutexs d'une application multi-thread possible, mais j'ignore si c'est une bonne pratique.
    Auriez-vous des conseils à me donner en ce qui concerne le design / modélisation de la gestion de la synchronisation des threads ? Merci !

  6. #6
    zul
    zul est déconnecté
    Membre chevronné Avatar de zul
    Profil pro
    Inscrit en
    Juin 2002
    Messages
    498
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2002
    Messages : 498
    Par défaut
    Disons qu'avec le pattern RAII, tu n'a pas à gérer la complexité de l'unlocking, si 1/ tu as des exceptions 2/ si tu as plein de conditions de sorties différentes (dans tous les chemins, il faut rajouter un unlock correctement).

    Sinon pour la place des mutex, ils doivent être déclarés / initialisés au plus prêt de la ressouce qu'ils protègent

  7. #7
    Membre averti
    Profil pro
    Inscrit en
    Août 2007
    Messages
    39
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2007
    Messages : 39
    Par défaut
    Ah oui, c'est vrai que l'unlock() est géré par le destructor, donc pas besoin de le répéter. Merci
    Par contre, je dois pas saisir quelque chose pour ce qui est de ta seconde remarque.
    Je prends un exemple simple :
    Ma ressource est stdout sur mon terminal, j'ai deux threads qui écrivent dessus.
    Or, ces deux threads sont différents (il ne s'agit pas de deux objets d'une même classe, ou de deux appels d'une même fonction).
    Cependant, il ne devrait y avoir qu'un seul mutex : si je déclare mon mutex au plus près de l'utilisation de la ressource, je le déclare dans chacun des deux threads, et donc cela ne sert plus à rien car il n'y aura pas d'exclusion.
    Jusqu'ici j'ai résolu cela en déclarant un mutex à portée globale.

    J'ignore cependant si tu veux dire "au plus près de la déclaration de la ressource" ou "au plus près de son utilisation". Si c'est le premier cas, pour peu que la ressource soit déclarée trois niveaux au-dessus (et que les niveaux soient des appels de fonction), je suis obligé de passer le mutex en argument à chaque appel de fonction pour maintenir sa portée. S'il s'agit de classes, je peux définir une base classe aux différents threads utilisant une même ressource avec un mutex comme membre statique, mais cette approche me paraît mauvaise pour plusieurs raisons, et c'est pourquoi je parlais d'une classe "manager de mutexs".

    Je suis sûr qu'il doit y avoir une modèle éprouvé pour ce problème malgré tout Merci !

  8. #8
    Membre très actif
    Profil pro
    Inscrit en
    Mai 2006
    Messages
    688
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2006
    Messages : 688
    Par défaut
    Euh .... comprendre effectuer le lock au plus prés de la ressource partagée à protégée. Pas la déclaration de l'objet mutex.

    L'idée sous jacente étant que tout le temps que le mutex est dans un état locké , les autres threads ayant besoin de ce mutex ne font rien. Ainsi moins de temps, en terme d'instruction processeur, un thread lock une ressource mieux c'est pour les performances générales de ton application multi threadé

  9. #9
    Membre averti
    Profil pro
    Inscrit en
    Août 2007
    Messages
    39
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2007
    Messages : 39
    Par défaut
    Salut,
    Ma question concerne donc la déclaration des mutexs : où les déclarer pour qu'elles soient partagées par tous les threads sans pour autant en faire des objets à portée globale. Merci !

  10. #10
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    Citation Envoyé par ehmicky Voir le message
    Salut,
    Ma question concerne donc la déclaration des mutexs : où les déclarer pour qu'elles soient partagées par tous les threads sans pour autant en faire des objets à portée globale. Merci !
    Dans l'objet qui sert d'interface thrad-safe pour accéder à ta ressource

  11. #11
    Membre averti
    Profil pro
    Inscrit en
    Août 2007
    Messages
    39
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2007
    Messages : 39
    Par défaut
    Merci beaucoup, sujet résolu ! Dans le doute où j'aurais mal compris quelque chose, je poste l'idée que j'ai compris :

    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
    class InterfaceThreadSafe
    {
        protected:
            Resource;
            Mutex;
        public:
            writeResource()
            {
                ...
                {
                    boost::unique_lock verrou(Mutex); 
                    ecrire(Resource);
                }
            }
    };
    class Thread
    {
        public:
            useResource()
            {
                     //ResourceInstance est une instance d'InterfaceThreadSafe
                     ResourceInstance.writeResource();
            }
    };
    Merci beaucoup à tous

    Edit : ok après m'être cassé la tête pendant 2 heures, je suis encore dans une impasse. Le problème dans ce que qui est marqué ci-dessus : si j'instancie plusieurs instances d'InterfaceThreadSafe, j'aurais plusieurs Mutex différents, et des Resource différents aussi. Et je peux pas passer comme argument par référence une même instance d'InterfaceThreadSafe, car cela plante (Mutex est nonCopyable). Donc je retombe sur la solution de la portée globale / singleton / membres static, qui m'embourbe dans quelque chose d'immonde.
    Merci beaucoup (je suis en train de devenir un peu dingue là )

  12. #12
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    Citation Envoyé par ehmicky Voir le message
    Et je peux pas passer comme argument par référence une même instance d'InterfaceThreadSafe, car cela plante (Mutex est nonCopyable).
    PAr référence, tu peux passer un objet non copiable et le stocker par référence dans ta classe.
    Citation Envoyé par ehmicky Voir le message
    Donc je retombe sur la solution de la portée globale / singleton / membres static, qui m'embourbe dans quelque chose d'immonde.
    Merci beaucoup (je suis en train de devenir un peu dingue là )
    TLS, pointeur, membre non statique, etc.

  13. #13
    Membre averti
    Profil pro
    Inscrit en
    Août 2007
    Messages
    39
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2007
    Messages : 39
    Par défaut
    J'y suis enfin arrivé !!
    Oui, l'ennui c'est que boost::mutex ne veut pas non plus être instantié avec une référence d'un autre mutex, le saligaud.
    Donc :
    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
    class InterfaceThreadSafe
    {
        protected:
            Resource;
            Mutex;
        public:
            write()
            {
                ...
                //Section critique
                {
                    Verrou(Mutex); 
                    action(Resource);
                }
            }
    };
    class Thread
    {
        protected:
            InterfaceThreadSafePointer*;
        public:
            Thread(InterfaceThreadSafePointer_copy*) : 
                InterfaceThreadSafePointer(InterfaceThreadSafePointer_copy) {};
            use() { InterfaceThreadSafePointer->write(); }
    };
    Ca parait si simple maintenant que j'ai vu Merci beaucoup !

  14. #14
    zul
    zul est déconnecté
    Membre chevronné Avatar de zul
    Profil pro
    Inscrit en
    Juin 2002
    Messages
    498
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2002
    Messages : 498
    Par défaut
    Pourquoi ne pas faire quelquechose comme ca ?

    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
     
    class InterfaceThreadSafe : public boost::noncopyable
    {
        protected:
            Resource resource;
            Mutex m;
        public:
            // initialize the resource, you own it
            InterfaceThreadSafe(args..) : resource(args...) {}
     
            write()
            {
                ...
                //Section critique
                {
                    Verrou(Mutex); 
                    action(Resource);
                }
            }
    };
     
    // copy a thread and its context does not have a clear semantic 
    class Thread : public boost::noncopyable
    {
        protected:
            InterfaceThreadSafe interface;
        public:
            Thread(args) : interface(args) {} 
            use() { interface.write(); }
    };

  15. #15
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    Reste plus qu'à gérer la durée de vie de ton pointeur.
    @zul : tu ne fais que de redécaler le problème non ? Car à la base il voulait une enveloppe de protection multithread à sa ressource qu'il partage entre plusieurs thread si j'ai bien compris.

  16. #16
    Membre averti
    Profil pro
    Inscrit en
    Août 2007
    Messages
    39
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2007
    Messages : 39
    Par défaut
    @zul : effectivement, comme le dit 3DArchi, je crois qu'enlever la solution du pointeur fait retomber sur le problème originel.
    @archi3D : merci, effectivement !

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

Discussions similaires

  1. [Thread] Reveiller un thread a partir d'un autre thread d'une autre classe
    Par arnolpourri dans le forum Concurrence et multi-thread
    Réponses: 18
    Dernier message: 11/04/2007, 15h18
  2. [MFC] rendre un thread membre d'une classe.
    Par giova_fr dans le forum MFC
    Réponses: 6
    Dernier message: 20/02/2006, 18h37
  3. Suite Thread Simultanés: instances de classe differentes?
    Par macgile dans le forum Framework .NET
    Réponses: 3
    Dernier message: 04/01/2006, 09h50
  4. [Thread] Erreur dans une classe interne
    Par totof2308 dans le forum Général Java
    Réponses: 5
    Dernier message: 03/06/2004, 08h15
  5. [Plugin] Comment instantier certaines classes de ANT ?
    Par relivio dans le forum Eclipse Platform
    Réponses: 2
    Dernier message: 01/04/2004, 15h45

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