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 :

Injection de multithread dans du code qui a 15 ans.


Sujet :

C++

  1. #1
    Membre chevronné
    Inscrit en
    Novembre 2006
    Messages
    362
    Détails du profil
    Informations forums :
    Inscription : Novembre 2006
    Messages : 362
    Par défaut Injection de multithread dans du code qui a 15 ans.
    Bonjours à nouveau,

    Il m'a été confié la délicate mission de délocaliser dans des threads secondaires des parties d'un programme qui a déjà bien vécu.

    Après avoir levé les bras bien haut et précisé que ce genre d'opération était risqué et que la délocalisation ne serait sans aucun doute que très partielle, j'ai mis ne place un ThreadManager qui sait lancer dans un nouveau thread une méthode avec des paramètres donnés, puis lorsque celui-ci est terminé, générer un évènement qui déclenchera une autre méthode dans mon thread principal.

    Quelque chose comme :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    class ThreadManager_core
    {
    public :
            template<       typename Class1, typename MethodForThread, typename ParamIn,
                            typename Class2, typename MethodAfterThread, typename ParamsOut
                    >
            void createThread(Class1*, MethodForThread, ParamIn*,Class2*, MethodAfterThread, ParamsOut*,HWND, ProgressHandler* pHandler=NULL);          // lance un thread
    }
    Donc je peux transformer des codes comme :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    void loadDatas(const std::string& sFileName)
    {
       Datas newDatas = loadDatasInFile(sFileName);
       createViewOfDatas(newDatas);
    }
    en
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    void loadDatas(const std::string& sFileName)
    {
       Datas newDatas;
       ThreadManager::get()->createThread(this,loadDatasInSecondaryThread,&sFileName,this,integrateDatas,&newDatas);
    }
    void loadDatasInSecondaryThread(const std::string& sFileName)
    {
       Datas newDatas = loadDatasInFile(sFileName);
    }
    void integrateDatas(Datas newDatas)
    {
       createViewOfDatas(newDatas);
    }
    La gestion des paramètres de mes deux méthodes est un peu plus complexe que cela, mais ce n'est pas ce qui nous intéresse ici.



    Ceci marche bien tant que la méthode que l'on exécute dans le thread n'accède pas aux mêmes variables que celles de mon thread secondaire. Or je ne connais pas la moitié du code de l'application que je modifie.

    J'ai réalisé un ThreadChecker qui vérifie que l'on est dans le thread principal. Et, si je suis cohérent, il me faut l'appeler partout dans mon programme, afin qu'il asserte si mes threads secondaires appelent des méthodes qui accèdent aux données de mon thread principal.

    Ce qui veut dire : modifier toutes les méthodes de tous les fichiers de mon programme.

    Avant de lançer ma moulinette qui va faire ça, je me demandais si quelqu'un envisageait une méthode plus class.
    J'ai pensé un moment définir une macro "{", quelque chose comme :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    # define { Tools::ThreadChecker::get()->checkThatYouAreInTheMainThread();
    Mais cela ne marchera pas, et puis cela promet de perdre tout futur codeur qui bossera sur le projet.

    Merci par avance à ceux qui pourront m'aider.

  2. #2
    Membre émérite
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    1 354
    Détails du profil
    Informations personnelles :
    Âge : 49
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 1 354
    Par défaut
    je te conseille boost::thread ... ne refais pas ce genre de chose...

  3. #3
    Membre émérite
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    1 354
    Détails du profil
    Informations personnelles :
    Âge : 49
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 1 354
    Par défaut
    ... utilise aussi openmp

    il permet justement de profiter du multi-core pour des programmes existants, puisqu'il agit a un niveau assez fin, les boucles

    openmp + boost::thread = pas mal d'ennuis en moins

  4. #4
    Membre émérite
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    1 354
    Détails du profil
    Informations personnelles :
    Âge : 49
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 1 354
    Par défaut
    aussi cela ne sert a rien de deporter en multi thread des bouts de codes que de toute facon on attend dessus ....

    as-tu des algos compliqués qui prennent du temps ?
    Que veux-tu vraiment ameliorer en utilisant des threads secondaires ?

  5. #5
    Membre chevronné
    Inscrit en
    Novembre 2006
    Messages
    362
    Détails du profil
    Informations forums :
    Inscription : Novembre 2006
    Messages : 362
    Par défaut
    Merci de ces si rapides réponses.

    J'aurais du préciser dans le message d'origine que je n'ai pas le droit, pour des raisons de politiques de gestion de projet qui ne sont pas de mon ressort, d'utiliser boost, ni d'ailleurs la moindre librairie ou le moindre bout de code qui ne soit déjà partie intégrante de mon projet.

    Merci tout de même

  6. #6
    Membre chevronné
    Inscrit en
    Novembre 2006
    Messages
    362
    Détails du profil
    Informations forums :
    Inscription : Novembre 2006
    Messages : 362
    Par défaut
    Citation Envoyé par epsilon68
    aussi cela ne sert a rien de deporter en multi thread des bouts de codes que de toute facon on attend dessus ....
    as-tu des algos compliqués qui prennent du temps ?
    Que veux-tu vraiment ameliorer en utilisant des threads secondaires ?
    Cela sert à pouvoir en lançer plusieurs à la fois, et à continuer d'utiliser l'IHM pendant ce temps.

    Le logiciel en question manipule des données assez lourdes et que le chargement et certains calculs prennent parfois plusieurs minutes.

  7. #7
    Membre émérite
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    1 354
    Détails du profil
    Informations personnelles :
    Âge : 49
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 1 354
    Par défaut
    c'est quoi comme IHM (Qt ? ... ? )

  8. #8
    Membre chevronné
    Inscrit en
    Novembre 2006
    Messages
    362
    Détails du profil
    Informations forums :
    Inscription : Novembre 2006
    Messages : 362
    Par défaut
    C'est du MFC.

  9. #9
    Membre émérite
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    1 354
    Détails du profil
    Informations personnelles :
    Âge : 49
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 1 354
    Par défaut
    parce que pas toutes les interfaces ne pourrait reagir a un evenement direct, mais plutot posté

  10. #10
    Membre émérite
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    1 354
    Détails du profil
    Informations personnelles :
    Âge : 49
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 1 354
    Par défaut
    MFC alors il faut posté un evenement qui dit que tu as fini de charger le fichier ... ou le calcul ... ou n'importe quoi, surtout pas appeler de fonction directe

    et quel compilateur ?

  11. #11
    Membre chevronné
    Inscrit en
    Novembre 2006
    Messages
    362
    Détails du profil
    Informations forums :
    Inscription : Novembre 2006
    Messages : 362
    Par défaut
    Citation Envoyé par epsilon68
    MFC alors il faut posté un evenement qui dit que tu as fini de charger le fichier ... ou le calcul ... ou n'importe quoi, surtout pas appeler de fonction directe
    On a du mal se comprendre, c'est exactement ce que je fais. Lors d'un appel de createThread la séquence est la suivante :
    - création d'un thread secondaire
    - le thread secondaire lance la première fonction
    - le thread secondaire poste un message au thread primaire
    - le thread primaire reçoit le message et lance la seconde fonction

    C'est même pour cette raison que j'ai découpé en deux fonctions.
    Mon problème est juste de vérifier que nulle part dans la première fonction on n'utilise des données accédées dans le thread principal.

    Citation Envoyé par epsilon68
    et quel compilateur ?
    Visual .net

  12. #12
    Membre émérite
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    1 354
    Détails du profil
    Informations personnelles :
    Âge : 49
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 1 354
    Par défaut
    ok mais tu ne pourra jamais savoir si ta variable est utilisé dans d'autre threads, il te faut mettre des garde fous ...

    vs.net 2005 ?

  13. #13
    Expert confirmé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2003
    Messages
    3 549
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Décembre 2003
    Messages : 3 549
    Par défaut
    Utilise des processus plutôt que des threads si tu veux être sûr qu'il n'y ait pas d'accès concurrents à une variable.

  14. #14
    Membre chevronné
    Inscrit en
    Novembre 2006
    Messages
    362
    Détails du profil
    Informations forums :
    Inscription : Novembre 2006
    Messages : 362
    Par défaut
    Citation Envoyé par epsilon68
    ok mais tu ne pourra jamais savoir si ta variable est utilisé dans d'autre threads, il te faut mettre des garde fous ...
    Comme le code est vieux, volumineux et que je ne le connais que très partiellement, mettre des zones critiques et/ou mutex sur les diverses variables risque d'être plutôt fastidieux.
    C'est bien là tout mon problème.

    Autrement dir : faire clean est exclu, il faut faire vite.

    Je penche donc vers un pis-aller qui est de me contenter de checker à l'exécution que
    - seules les méthodes que je marque sont appelées dans les threads secondaires.
    - aucune méthode que je marque n'est appelée dans un trhead primaire.

    Ca ne garantis pas qu'il n'y aura pas un partage de mémoire malencontreux. Cela garantis que si je sais faire en sorte que les méthodes marquées ne touchent pas les même données que les méthodes non marquées, alors je n'aurais pas de partage malencontreux.

    Mais je suis à la recherche d'une meilleure idée, tant que ça peut être réalisé sans comprendre le détail du code.

    Citation Envoyé par epsilon68
    vs.net 2005 ?
    Non 2003.

  15. #15
    Membre émérite
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    1 354
    Détails du profil
    Informations personnelles :
    Âge : 49
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 1 354
    Par défaut
    Tu vas a peu pres droit dans le mur...

  16. #16
    Membre chevronné
    Inscrit en
    Novembre 2006
    Messages
    362
    Détails du profil
    Informations forums :
    Inscription : Novembre 2006
    Messages : 362
    Par défaut
    Citation Envoyé par epsilon68
    Tu vas a peu pres droit dans le mur...
    Oui, bien sur, il n'y a qu'une alternative : faire au propre ou ne rien faire.

    Malheureusement, au quotidien, il faut souvent travailler à partir de code qui n'a pas été pensés comme tu le souhaitais, et ce sans avoir le temps de tout refaire.

    Si tu connais d'autres conditions de travail, cela m'intéresse de savoir où tu bosses, j'enverrais un CV.

  17. #17
    Membre émérite
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    1 354
    Détails du profil
    Informations personnelles :
    Âge : 49
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 1 354
    Par défaut
    :-)

  18. #18
    Membre émérite
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    1 354
    Détails du profil
    Informations personnelles :
    Âge : 49
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 1 354
    Par défaut
    Citation Envoyé par Feriaman
    Oui, bien sur, il n'y a qu'une alternative : faire au propre ou ne rien faire.
    Ce n'est pas tout l'un ou tout l'autre, mais dans des cas comme ca il faut pas foncer la tete la premiere et faire du code parce qu'il faut faire tout de suite.

    Cela necessite du refactoring de code, comprendre abstraire.
    "propre" ne veut en soi rien dire, il faut au moins que ce soit robuste.
    mais faire pour faire, ca va tout le temps droit au mur. au final tu paniques pour ne rien gagner a la fin.

    a+

  19. #19
    tut
    tut est déconnecté
    Membre éclairé
    Avatar de tut
    Inscrit en
    Juillet 2002
    Messages
    373
    Détails du profil
    Informations forums :
    Inscription : Juillet 2002
    Messages : 373
    Par défaut
    faudrait que tu demandes à ton responsable s'il connait la différence entre l'informatique et la magie ?
    Les solutions que tu veux mettre en place me semble un peu trop bricolées, hélas... ce n'est pas un jugement, mais je constate avec toi que tu es pris par le temps.
    Peut-être que tu devrais prendre le problème d'un point de vue fonctionnel : "quand je fais telle opération, l'IHM est figée, qu'est-ce que je peux faire pour que ce ne soit plus le cas ?" plutôt que de vouloir tout changer en entier...

    Sinon, pour le problème des variables partagées, j'ai écrit une classe il y'a quelques temps qui permettait de faire évoluer un attribut de classe de "normal" vers "protégé par un mutex" en ne changeant que 5-10 % du code où est utilisé l'attribut :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    int m_MonAttribut;
    devient :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    JMMutex<int> m_MonAttribut;
    et puis voila, l'attribut est "protégé" des lectures/écritures concourantes par Mutex.
    Si ça peut t'aider je peux te l'envoyer => MP.
    Bon courage, en tout cas....

  20. #20
    Membre chevronné
    Inscrit en
    Novembre 2006
    Messages
    362
    Détails du profil
    Informations forums :
    Inscription : Novembre 2006
    Messages : 362
    Par défaut
    Merci de vos encouragements.

    Citation Envoyé par tut
    faudrait que tu demandes à ton responsable s'il connait la différence entre l'informatique et la magie ?
    J'ai commençé par prévenir du danger ... et des phrases comme : "non seulement le code que l'on va livrer provoquera peut-être des plantages impossible à diagnostiquer, mais en plus il est probable que ces plantages ne se produisent jamais pendant la phase de test" n'ont pas suffit à le décourager.

    Donc je me dis qu'il sait ce qu'il veut. La décision étant prise, il me faut le réaliser. Actuellement ça marche sans aucune vérification du partage de la mémoire, et tout le monde s'en tamponne sauf moi ... j'aimerais quand même mettre en place rapidement un système qui permette, si ce n'est d'éviter le mur, au moins de le voir.

    Citation Envoyé par tut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    JMMutex<int> m_MonAttribut;
    Je devrais peut-être m'orienter vers quelque chose comme ça, mais plutot que de tout protéger par mutex (ce qui me provoquerait, presque à coup sur des deadlocks), garder un booléen qui m'indique si le thread dans lequel la variable est utilisée est le thread principal où non, et qui asserte en cas de problème.


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    template<typename T> AssertIfUsedBy2Threads
    {
       private : 
          bool bMainThread;
       public : 
          /*l'ensemble de mes opérateurs*/
    }
    Et ensuite quelque chose de barbare comme :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    #define int AssertIfUsedBy2Threads<int>
    J'en ai déjà mal au coeur.

    Ca semble réalisable ?
    Il faut que j'y réflechisse.

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. [AC-2007] Erreur de compilation dans un code qui pourtant fonctionne
    Par cslbcg dans le forum VBA Access
    Réponses: 4
    Dernier message: 06/11/2009, 23h11
  2. un probléme dans un code qui m'a géné
    Par jack_1981 dans le forum VB 6 et antérieur
    Réponses: 2
    Dernier message: 10/01/2008, 17h53
  3. [DOM] java.lang.ClassCastException dans un code qui modifie un fichier XML
    Par RouRa22 dans le forum Format d'échange (XML, JSON...)
    Réponses: 1
    Dernier message: 21/12/2007, 16h21
  4. Réponses: 8
    Dernier message: 26/11/2007, 17h02
  5. Réponses: 9
    Dernier message: 06/08/2007, 01h37

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