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 :

Communication entre threads


Sujet :

Boost C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé Avatar de kidpaddle2
    Inscrit en
    Avril 2006
    Messages
    430
    Détails du profil
    Informations forums :
    Inscription : Avril 2006
    Messages : 430
    Par défaut Communication entre threads
    Bonjour,

    J'ai trois problèmes dans l'utilisation de boost::thread (ça m'étonne qu'il y ait si peu de tutoriaux à ce sujet, le tutorial de developpez.com manque de réels exemples) :
    1. J'ai une donnée stockée dans le thread principal, qui est écrite par un thread de lecture de fichier et lue par un thread de calcul : est-ce qu'un mutex est quand même nécessaire, même s'il n'y a pas deux écritures en même temps ?
    2. Si oui, en utilisant l'encapsulation suivante, j'ai un paquet d'erreur de compilation pointant sur du boost::noncopyable... Que manque-t-il ?
      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
      //L'instance de cette classe est stockée via le thread principal
      class A {
         //Données...
       
         boost::mutex m_data_mutex;  
       
         public:
            //Cette méthode est appelée par le thread de lecture de fichiers
            void write( /* data input */ ) {
               boost::mutex::scoped_lock lock(m_data_mutex);
       
               //Operation d'ecriture
            }
       
            /* data output */ read() {
               boost::mutex::scoped_lock lock(m_data_mutex);
       
               //Operation de lecture
            }
      };
    3. Comment (visiblement quelque chose avec boost::condition) avertir un thread qu'une donnée est prête à être lue ? En fait, je pensais encapsuler comme suit :
      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 Written_then_read {
          protected:
              Written_then_read() : m_ready(false);
       
              boost::mutex m_data_mutex;
              boost::condition m_cond;
       
              bool m_ready;
       
              typedef boost::mutex::scoped_lock Lock;
       
              Lock filling() {
                  m_ready = true;
                  m_cond.notify_one();
       
                  return Lock(m_data_mutex);
              }
       
              void wait_for_fill() {
                  Lock lock(m_data_mutex);
                  while(!m_ready) {
                     m_cond.wait(lock);
                  }
              }
      };
      ... Et l'utiliser comme suit :
      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
      class A : private Written_then_read {
         //...
       
         void write( /* data input */ ) {
            Lock lock = filling();
       
            //Fill
         }
       
         /* data output */ read() {
            wait_for_fill();
       
            //Read
         }
       
         //...
      };
      Mais cela ne pose-t-il pas des problèmes de copie à nouveau ?


    Merci d'avance.

    Cordialement,

    Kidpaddle2

    P.S: J'utiliserai probablement ce topic pour les problèmes relatifs à la résolution de ces questions

  2. #2
    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
    boost::mutex et boost::scoped_lock sont non copiable. Tu ne peux donc pas les copier (jusque là ça parait évident). Tu ne peux pas plus copier A avec l'opérateur par défaut, parce qu'il va essayer de copier le mutex (donc soit A devient noncopyable, soit il faut gérer la copie de A correctement).

    De manière général les lockers sont prévu pour survivre uniquement dans le scope d'une section critique, ils ne sont pas prévu pour être copié et passer à d'autres contextes.

    [edit1] En général, si ton read et ton write ne sont pas atomatiques, tu as besoin d'établir une ressource critique sur ces sections (avec un mutex ici). Pour la geston des conditions, je ne comprend pas bien le while () { wait() }; wait est par définition bloquant, et finira uniquement quand quelqu'un aura notifié que quelquechose est prêt (ready est donc redondant en plus).

  3. #3
    Membre éclairé Avatar de kidpaddle2
    Inscrit en
    Avril 2006
    Messages
    430
    Détails du profil
    Informations forums :
    Inscription : Avril 2006
    Messages : 430
    Par défaut
    Même en héritant de noncopyable, read() renvoie une valeur Lock, donc appelle le constructeur de copie... Mais je ne vois pas d'autres manières pour modulariser...

    En ce qui concerne m_read, c'est pour éviter que le writer n'accède aux ressources alors qu'elles n'ont pas été encore lues (donc lockées).
    Mais j'y pense, n'est-il pas possible, avec un simple booleen, de ne pas recourir aux mutexes ? Etant donné qu'une fois le remplissage terminé, les données ne seront plus modifiées : un booleen m_ready serait-il donc thread-safe dans ce cas précis ?

  4. #4
    Expert confirmé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2005
    Messages
    5 502
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Conseil

    Informations forums :
    Inscription : Février 2005
    Messages : 5 502
    Par défaut
    Non.

    Imaginez le cas où chaque thread s'exécute simultanément sur un cœur différent du CPU multi-cœur, que la valeur de la variable m_ready est dans deux registres différents, chacun dans un des cœurs.

  5. #5
    Expert confirmé
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 296
    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 296
    Par défaut
    Je ne peux que te conseiller d'échanger des données via queues de messages (si échanges réguliers). Ou alors voir du côté des futures et autres barrières.
    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...

  6. #6
    Membre éclairé Avatar de kidpaddle2
    Inscrit en
    Avril 2006
    Messages
    430
    Détails du profil
    Informations forums :
    Inscription : Avril 2006
    Messages : 430
    Par défaut
    Ca peut être intéressant à implémenter effectivement. Je vais me pencher là-dessus sérieusement. Par contre, est-ce que je peux faire ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    class Reader : public concurrent_queue<CSVFile::Row> {
           void read() {
               //Ouvrir le fichier et faire une boucle en appelant m_data.push() sur chaque ligne lue
           }
     
           public:
               void run() {
                   //Lancer un thread sur read()
               }
     
               ~Reader() {
                   //Rejoindre
               }
    };
    ?
    Sachant que j'aurais plusieurs instances, et que dans un autre thread, j'appellerais wait_and_pop() de chacun pour calculer.

    Edit: J'ai fait un petit test, en faisant cela, ça marche. Mais est-ce qu'il y a un problème éventuel que je n'aurais pas vu ?

    Qu'en pensez-vous ?

Discussions similaires

  1. [C#] Communication entre thread
    Par kekesilo dans le forum Windows Forms
    Réponses: 11
    Dernier message: 17/09/2007, 19h48
  2. [thread] communication entre threads
    Par untipy dans le forum Concurrence et multi-thread
    Réponses: 11
    Dernier message: 30/08/2007, 15h47
  3. Problème de communications entre threads
    Par maya09 dans le forum Windows
    Réponses: 1
    Dernier message: 22/02/2006, 22h18
  4. Communication entre thread
    Par JFPS Soft dans le forum Concurrence et multi-thread
    Réponses: 2
    Dernier message: 03/02/2006, 17h38
  5. [c#][threading] communication entre threads
    Par orelero dans le forum C#
    Réponses: 6
    Dernier message: 02/01/2006, 00h42

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