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 :

Concurrence et Programmation par contrat.


Sujet :

Threads & Processus C++

  1. #1
    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
    Points : 13 017
    Points
    13 017
    Par défaut Concurrence et Programmation par contrat.
    Bonjour,
    Peut-on dire les choses suivantes dans le cadre de la programmation par contrat :
    -> Une fonction ré entrante : les invariants sont préservés pendant toute la durée de la fonction.
    -> Une fonction Thread-safety : les invariants peuvent être rompus au sein d'une section protégée (mutex/section critique, etc.).

    On sent un certain flottement dans la définition de réentrance vis à vis de thread-safety. Aussi, je me demandais si cette approche ne permet pas de bien comprendre la différence.

    Ai-je tout faux ?

  2. #2
    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
    Points : 13 017
    Points
    13 017
    Par défaut
    Bon, je crois que j'ai faux
    La réentrance est en général définie comme la possibilité d'appeler une même fonction avec des paramètres différents. Donc, je peux très bien casser quelques invariants de mon objet courant pendant l'exécution de cette fonction sur celui-ci et appeler la fonction sur un autre objet. Cela va plus être lié aux éventuels variables statiques de la classe (ou variables globales).
    A l'inverse une fonction thread-safe doit pouvoir être appelée par plusieurs threads sur le même objet. J'ai donc pas trop intérêt à casser les invariants...

    A votre avis, comment s'articulent les invariants avec la réentrance et le thread-safety ?

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

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Si tu comprends l'anglais, ceci peut te donner à réfléchir:
    http://blogs.msdn.com/oldnewthing/ar...29/168719.aspx

    Le problème, c'est que dès qu'on se met à parler d'autres choses que des variables globales/statiques, la notion devient floue : Une fonction agissant sur deux objets pourrait être dite thread-safe sur un des objets et pas l'autre!
    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.

  4. #4
    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
    Points : 13 017
    Points
    13 017
    Par défaut
    Merci pour le lien. J'étais déjà tombé dessus. Et sur bien d'autres. Ce qui m'a justement amené à penser que cette notion de réentrance (à l'origine venant du monde de la programmation système et applicable dans le cadre des interruptions) avait du mal à être consensuellement définie dans le cadre de la programmation concurrente. A la limite, thread-safe parait plus facile à définir : grossièrement thread-safe = pas de race conditions -> utilisation de verrous si nécessaire.

  5. #5
    Expert éminent sénior
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 275
    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 275
    Points : 10 985
    Points
    10 985
    Par défaut
    "reentrant" marche bien dans le cadre de la prog concurrente : il n'y a pas d'effet de bord visible (ou plutôt de type aberrant/tombe en marche) sur le résultat de la fonction à cause d'exécutions parallèles de celle-ci.

    Dès que tu as un état partagé (var globale/statique, ou membre) qui peut évoluer et influencer le résultat pour produire des sorties indésirables, ce n'est pas réentrant.
    J'ai tendance à considérer, à tord peut-être, qu'une fonction qui trace son nombre max d'exécutions parallèles comme "réentrante" si elle est justement capable de sortir ce nombre max.

    EDIT: Hum ... on retrouve la notion de MT-safe -- BTW, plutôt que les locks les TSS/TLS marchent bien aussi.
    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
    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
    Points : 13 017
    Points
    13 017
    Par défaut
    Citation Envoyé par Luc Hermitte Voir le message
    "reentrant" marche bien dans le cadre de la prog concurrente : il n'y a pas d'effet de bord visible (ou plutôt de type aberrant/tombe en marche) sur le résultat de la fonction à cause d'exécutions parallèles de celle-ci.
    Cette définition est un peu forte par rapport à ce qu'on trouve dans la littérature. "Pas d'effet de bord sur le résultat si exécution //" -> Il suffirait alors de protéger l'accès aux variables globales pour qu'une fonction soit réentrante. On trouve plutôt une distinction :
    -> réentrant = peut être appelée concurremment avec des jeu de données différents (donc pas d'état partagé) + peut avoir des appels imbriqués dans une même tâche
    -> thread-safe = peut être appelée concurremment avec un jeu de données identique + la garantie n'est assurée à priori que sur des tâches différentes


    Citation Envoyé par Luc Hermitte Voir le message
    Dès que tu as un état partagé (var globale/statique, ou membre) qui peut évoluer et influencer le résultat pour produire des sorties indésirables, ce n'est pas réentrant.
    C'est souvent présenté comme 'une fonction réentrante ne dépend que des paramètres qu'elle prend en entrée et ne retourne en sortie rien d'interne/globale. Une fonction réentrante est une fonction 'sans mémoire'.

    Citation Envoyé par Luc Hermitte Voir le message
    J'ai tendance à considérer, à tord peut-être, qu'une fonction qui trace son nombre max d'exécutions parallèles comme "réentrante" si elle est justement capable de sortir ce nombre max.

    Citation Envoyé par Luc Hermitte Voir le message
    EDIT: Hum ... on retrouve la notion de MT-safe -- BTW, plutôt que les locks les TSS/TLS marchent bien aussi.
    Google + TSS = "Tout Sauf Sarkosy"
    Google + TLS = "Transport Layer Security"
    J'imagine que ce n'est pas tout à fait de ce sens dont tu parles...
    Entres parenthèses, lock : facilité de langage car partagé par tous ceux qui font du multi-thread (MT).

  7. #7
    Expert éminent sénior
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 275
    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 275
    Points : 10 985
    Points
    10 985
    Par défaut
    En effet, je n'avais pas intégré proprement la notion de mémoire.

    Sinon TLS = Thread-Local Storage
    TSS = Thread-Static Storage (ou Specific Storage ?)

    Les locks sont une solution du pauvre parfois adaptés, mais souvent abusés. Aujourd'hui je m'en méfie énormément, j'ai eu trop de mauvaises surprises et autres designs bancals à base de locks. Je cherche d'abord à éviter les états partagés. Cf les articles d'H.Sutter pour plus d'infos.
    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...

  8. #8
    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
    Points : 13 017
    Points
    13 017
    Par défaut
    Citation Envoyé par Luc Hermitte Voir le message
    Les locks sont une solution du pauvre parfois adaptés, mais souvent abusés. Aujourd'hui je m'en méfie énormément, j'ai eu trop de mauvaises surprises et autres designs bancals à base de locks.
    Je cherche d'abord à éviter les états partagés.
    Ben, c'est certainement la première solution aux race conditions mais qu'on a du mal à bien appréhender les conséquences et notamment les scénarii de deadlock qui en découlent. Mais je comprend mieux ta remarque sur le TLS. L'objectif est d'éliminer les dépendances entre les différentes tâches de façon à ne pas avoir à utiliser les mécanismes de lock.

    Citation Envoyé par Luc Hermitte Voir le message
    Cf les articles d'H.Sutter pour plus d'infos.
    Il y en a tout une palanqué ici et ici. Tu penses auquel ?

  9. #9
    Membre chevronné
    Avatar de Goten
    Profil pro
    Inscrit en
    Juillet 2008
    Messages
    1 580
    Détails du profil
    Informations personnelles :
    Âge : 33
    Localisation : France

    Informations forums :
    Inscription : Juillet 2008
    Messages : 1 580
    Points : 2 205
    Points
    2 205
    Par défaut
    C'est les mêmes sur les deux pages. Btw ils sont tous très instructif.
    "Hardcoded types are to generic code what magic constants are to regular code." --A. Alexandrescu

  10. #10
    Inactif  
    Avatar de Mac LAK
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    3 893
    Détails du profil
    Informations personnelles :
    Âge : 49
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Octobre 2004
    Messages : 3 893
    Points : 4 846
    Points
    4 846
    Par défaut
    Citation Envoyé par 3DArchi Voir le message
    Il suffirait alors de protéger l'accès aux variables globales pour qu'une fonction soit réentrante.
    C'est en général ainsi que l'on rend une fonction réentrante quand elle ne l'est pas par conception...

    Citation Envoyé par 3DArchi Voir le message
    C'est souvent présenté comme 'une fonction réentrante ne dépend que des paramètres qu'elle prend en entrée et ne retourne en sortie rien d'interne/globale. Une fonction réentrante est une fonction 'sans mémoire'.
    Réentrante veut dire "interruptible par elle-même sans effets de bords". Ce qui veut dire, en pratique, que deux threads (ou deux processus, en fonction du niveau de parallélisme visé) exécutant ladite fonction en même temps peuvent s'interrompre l'un-l'autre sans effets de bord... Il va sans dire qu'une section critique bovine sur l'intégralité de la fonction, la rendant ainsi atomique, est une solution... Peu performante, par contre.

    Si la fonction ne peut pas être réentrante par conception (ex : accès à une ressource critique et/ou unique sur la machine), la CS devra alors être la plus courte possible pour satisfaire la réentrance.

    La manière la plus simple de rendre une fonction réentrante par conception, c'est effectivement de ne la faire dépendre que de ses paramètres, et de n'utiliser dedans que des appels à des fonctions elles-mêmes réentrantes (ex : strtok ne l'est pas, tout comme les fonctions de gestion des arguments variables, si le compilateur ne génère pas du code pour conserver l'état dans le TLS). Bien sûr, l'utilisation d'un contexte global quelconque est prohibé...
    Contrairement à une idée répandue, une fonction ayant un argument "static" (c'est à dire avec mémoire !!) peut être réentrante. Il faut et il suffit de stocker cette donnée dans le TLS justement. Dans certains cas spécifiques (compteurs d'itération par exemple), on peut également utiliser une fonction Interlocked*, qui a la particularité intéressante de ne quasiment pas coûter de temps machine supplémentaire par rapport à l'opération non-atomique.


    Un autre point : quand tu parles d'appels imbriqués, c'est extrêmement trompeur, car tu définis en fait une fonction récursive et réentrante... Ce qui est un cas plutôt particulier !!

    Thread-safe : La réentrance est garantie entre tous les threads au sein d'un même processus. La protection envers un autre processus concurrent n'est pas garantie.
    Process-safe : La réentrance est garantie au niveau système pour tout processus (à fortiori tous les threads d'un processus) utilisant la fonction. Surtout utilisé dans le monde des drivers et du noyau.
    Mac LAK.
    ___________________________________________________
    Ne prenez pas la vie trop au sérieux, de toutes façons, vous n'en sortirez pas vivant.

    Sources et composants Delphi sur mon site, L'antre du Lak.
    Pas de question technique par MP : posez-la dans un nouveau sujet, sur le forum adéquat.

    Rejoignez-nous sur : Serveur de fichiers [NAS] Le Tableau de bord projets Le groupe de travail ICMO

  11. #11
    Expert éminent

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Points : 6 911
    Points
    6 911
    Par défaut
    Une fonction reentrante pour moi ne peut pas dependre d'un etat global sans que celui-ci soit passe en parametre. Si elle pose un lock, c'est sur un mutex dont l'adresse lui est passe. (Elle ne peut pas poser un lock sur un mutex global parce que si elle redemarre dans la partie critique, la deuxieme execution a un gros probleme).

    Je suis loin d'etre sur qu'il y a une notion de "fonction thread-save" absolue. C'est comme pour le cas des fonctions "exception-save", il y a differentes garanties en fonction des contraintes qu'on pose sur les parametres. Il y a de meme en pratique differentes garanties suivant les contraintes qu'on place sur les appels a d'autres fonctions (je pense en particulier au cas des fonctions membres du meme objet). La reentrance est un moyen d'atteindre le niveau ou les parametres doivent etre "independants" pour une definition d'independant qui va dependre de la fonction.
    Les MP ne sont pas là pour les questions techniques, les forums sont là pour ça.

  12. #12
    Inactif  
    Avatar de Mac LAK
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    3 893
    Détails du profil
    Informations personnelles :
    Âge : 49
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Octobre 2004
    Messages : 3 893
    Points : 4 846
    Points
    4 846
    Par défaut
    Citation Envoyé par Jean-Marc.Bourguet Voir le message
    Une fonction reentrante pour moi ne peut pas dependre d'un etat global sans que celui-ci soit passe en parametre.
    Et pourtant, si, elle peut... Ceci étant dit, ce sont des cas assez particuliers en général, mais strtok est l'exemple parfait d'une telle fonction, du moins dans les CLib suffisamment évoluées pour l'avoir en version réentrante.

    Citation Envoyé par Jean-Marc.Bourguet Voir le message
    Si elle pose un lock, c'est sur un mutex dont l'adresse lui est passe. (Elle ne peut pas poser un lock sur un mutex global parce que si elle redemarre dans la partie critique, la deuxieme execution a un gros probleme).
    Là, j'ai du mal de te suivre par contre : un mutex, c'est un mutex, global ou pas. Une fois pris, personne d'autre ne peut le prendre, il n'y a pas de risque d'auto-blocage s'il est pris correctement.
    Et une fonction réentrante grâce à un mutex n'a, normalement, pas à se protéger d'autre chose que d'elle-même. Si ce n'est pas le cas, on commence à se rapprocher dangereusement des fonctions process-safe dans leur principe.

    Citation Envoyé par Jean-Marc.Bourguet Voir le message
    Je suis loin d'etre sur qu'il y a une notion de "fonction thread-save" absolue.
    Oh, si, il y en a plein même. Mais ce sont le plus souvent des fonctions de calcul "pur".

    Exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    int AbsoluteReentrant ( const int Data1, const int Data2 ) {
      return (Data1+Data2) ;
    }
    Certes, c'est minimaliste, mais c'est totalement réentrant quel que soit la plate-forme, l'OS, le scheduling, etc.

    Quant aux fonctions "exception-safe", c'est un tout autre problème... Elles sont en général safe par rapport aux cas nominaux et aux cas dégradés CONNUS. Mais un changement d'implémentation (notamment une nouvelle classe d'exceptions inconnue jusque là dans les sous-fonctions) risque de poser de gros problèmes.

    Au niveau de la réentrance, c'est plus difficile d'avoir un tel risque : il arrive régulièrement que des fonctions qui n'étaient pas thread-safe (ou process-safe) le deviennent, au sein des librairies et OS. L'inverse n'arrive habituellement jamais sans renommer explicitement la fonction, donc sans impact sur le code déjà compilé.
    Mac LAK.
    ___________________________________________________
    Ne prenez pas la vie trop au sérieux, de toutes façons, vous n'en sortirez pas vivant.

    Sources et composants Delphi sur mon site, L'antre du Lak.
    Pas de question technique par MP : posez-la dans un nouveau sujet, sur le forum adéquat.

    Rejoignez-nous sur : Serveur de fichiers [NAS] Le Tableau de bord projets Le groupe de travail ICMO

  13. #13
    Expert éminent

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Points : 6 911
    Points
    6 911
    Par défaut
    Citation Envoyé par Mac LAK Voir le message
    Et pourtant, si, elle peut... Ceci étant dit, ce
    sont des cas assez particuliers en général, mais strtok est l'exemple
    parfait d'une telle fonction, du moins dans les CLib suffisamment évoluées
    pour l'avoir en version réentrante.
    Tu peux appeler strtok avec ces versions dans un gestionnaire de signal?
    Ca se passe comment?

    Là, j'ai du mal de te suivre par contre : un mutex, c'est un mutex,
    global ou pas.
    Je veux dire un mutex connu de la fonction par rapport a un mutex dont on a
    passe l'adresse.

    Une fois pris, personne d'autre ne peut le prendre, il n'y a
    pas de risque d'auto-blocage s'il est pris correctement.
    A nouveau, appel d'un gestionnaire de signal pendant que le mutex est pris.

    Oh, si, il y en a plein même. Mais ce sont le plus souvent des
    fonctions de calcul "pur".
    Je ne voulais pas dire qu'il n'y avait pas de fonctions qui soient
    thread-safe pour toute definition raisonnable de fonction (les fonctions
    "pures" des langages fonctionnels le sont) mais que quand on aborde ce
    sujet, il est interessant d'introduire plus que deux cas, thread-safe ou
    pas.

    Quant aux fonctions "exception-safe", c'est un tout autre
    problème... Elles sont en général safe par rapport aux cas nominaux et
    aux cas dégradés CONNUS
    . Mais un changement d'implémentation (notamment
    une nouvelle classe d'exceptions inconnue jusque là dans les
    sous-fonctions) risque de poser de gros problèmes.
    La grosse majorite (et je ne dis pas la totalite parce que je n'exclus pas
    un cas bizarre, mais je n'ai pas d'exemple ou ce ne soit pas le cas en
    tete) des mes fonctions exception-safe ne dependent que du fait que
    quelques briques de base (du genre operations ne changeant pas l'etat,
    assignation de types fondamentaux, operations swap, ...) ne jettent jamais
    d'exception. Elles se foutent completement de la nature des exceptions que
    peuvent jeter les autres operations.
    Les MP ne sont pas là pour les questions techniques, les forums sont là pour ça.

  14. #14
    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
    Points : 13 017
    Points
    13 017
    Par défaut
    Citation Envoyé par Jean-Marc.Bourguet Voir le message
    Je ne voulais pas dire qu'il n'y avait pas de fonctions qui soient
    thread-safe pour toute definition raisonnable de fonction (les fonctions
    "pures" des langages fonctionnels le sont) mais que quand on aborde ce
    sujet, il est interessant d'introduire plus que deux cas, thread-safe ou
    pas.
    Salut,
    Tu peux développer ou un lien vers quelque chose qui explique ce point de vue ? J'ai du mal à suivre ce que tu veux dire par "[il y a plus que ] thread-safe ou pas".
    Merci.

  15. #15
    Expert éminent

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Points : 6 911
    Points
    6 911
    Par défaut
    Citation Envoyé par 3DArchi Voir le message
    Salut,
    Tu peux développer ou un lien vers quelque chose qui explique ce point de vue ? J'ai du mal à suivre ce que tu veux dire par "[il y a plus que ] thread-safe ou pas".
    Merci.
    J'ai deja trois niveaux facilement pour les membres d'un objet:
    - pas thread-safe du tout (depend qu'une variable globale non protegee ne soit pas modifiee par exemple)
    - thread safe tant qu'on l'appelle sur des objets differents (elle modifie l'objet mais celui-ci n'est pas protege par un mutex, c'est ce que fournissent classiquement les implementations de la SL "thread-safe")
    - thread safe meme quand on l'appelle sur le meme objet (elle se contente de lire des informations ou elle fait des modifications en se protegeant)

    Et comme je l'ai dit, des qu'il y a plus d'un membre, il faut aussi definir les interractions entre eux (par exemple les membres faisant uniquement de la lecture sont compatibles entre eux sur un meme objet mais pas avec ceux qui le modifient)
    Les MP ne sont pas là pour les questions techniques, les forums sont là pour ça.

  16. #16
    Inactif  
    Avatar de Mac LAK
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    3 893
    Détails du profil
    Informations personnelles :
    Âge : 49
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Octobre 2004
    Messages : 3 893
    Points : 4 846
    Points
    4 846
    Par défaut
    (Note : Pas agréable, les retours à la ligne manuels...)

    Citation Envoyé par Jean-Marc.Bourguet Voir le message
    Tu peux appeler strtok avec ces versions dans un gestionnaire de signal?
    J'utilise très peu de gestionnaires de signal, étant sous Windows la plupart du temps. Tout dépend du contexte d'exécution du gestionnaire, déjà, donc par quel thread il est exécuté.
    Ensuite, je le répète, la réentrance d'une fonction, c'est vis-à-vis d'elle même, et exclusivement d'elle-même. Deux fonctions différentes ne sont pas "réentrantes" entre elles, on parle plutôt d'interruptibilité (ou non) de l'une par l'autre.

    Donc : si strtok est interceptée par elle-même par un gestionnaire de signal, pendant sa partie critique éventuelle, les cas possibles sont :
    • Le contexte d'exécution est le même (pas de commutation de thread), la CS est donc déjà obtenue. Pas d'interblocage, mais il y aura corruption du strtok interrompu si ça fonctionne avec le TLS. On peut toutefois gérer ce cas très facilement via un compteur de réentrance.
    • Le contexte d'exécution est différent : le gestionnaire de signal est donc dans un autre thread, qui ne pourra pas acquérir le mutex (s'il existe) jusqu'à la prochaine inversion de priorité. Si c'est géré par TLS, aucun souci.


    Côté tripaille interne de la fonction, il est donc possible de la rendre totalement réentrante... Reste à savoir si c'est fait ou pas dans la CLib de ton compilo préféré ou pas, l'analyse des sources étant encore le meilleur moyen de le savoir.

    Citation Envoyé par Jean-Marc.Bourguet Voir le message
    Je veux dire un mutex connu de la fonction par rapport a un mutex dont on a passe l'adresse.
    Et je ne vois toujours pas le problème : un mutex étant quelque chose de "global" (au moins au niveau du processus), tu n'as pas à le passer à une fonction qui doit être réentrante, sauf s'il y a un mécanisme bien plus haut qui assure l'utilisation correcte dudit mutex "global".
    Un mutex de réentrance, c'est un mutex en général nommé, en singleton sur le processus ou sur le système (selon les besoins), et exclusivement dédié à la fonction en question. Personne d'autre ne doit le connaître, ni l'utiliser.

    Citation Envoyé par Jean-Marc.Bourguet Voir le message
    Je ne voulais pas dire qu'il n'y avait pas de fonctions qui soient thread-safe pour toute definition raisonnable de fonction (les fonctions "pures" des langages fonctionnels le sont) mais que quand on aborde ce sujet, il est interessant d'introduire plus que deux cas, thread-safe ou pas.
    Je dirais plutôt qu'il est important de savoir ce que veut réellement dire "thread-safe", la plupart des gens n'en ayant qu'une vague notion.

    Pour moi, si une fonction est déclarée "thread-safe", je fais n'importe quoi, n'importe comment et dans n'importe quel thread avec. Si ça explose, je vais chercher une "explication" avec celui qui a osé prétendre qu'elle était thread-safe...

    Citation Envoyé par Jean-Marc.Bourguet Voir le message
    La grosse majorite des mes fonctions exception-safe ne dependent que du fait que quelques briques de base ne jettent jamais d'exception.
    Donc, déjà, elles ne sont pas exception-safe : pour avoir ce "label" (difficile à avoir, je reconnais), faut être parano et considérer que même la ligne de commentaire pourrait être fourbe et lancer une exception elle aussi...

    Tout dépend aussi de ce que l'on veut dire réellement par "exception-safe", c'est presque un débat à part entière... Certains le lisent "laisser passer les exceptions", d'autres "ne pas être perturbé par une exception"... Et les deux manières de voir donnent une implémentation radicalement différente.
    Mac LAK.
    ___________________________________________________
    Ne prenez pas la vie trop au sérieux, de toutes façons, vous n'en sortirez pas vivant.

    Sources et composants Delphi sur mon site, L'antre du Lak.
    Pas de question technique par MP : posez-la dans un nouveau sujet, sur le forum adéquat.

    Rejoignez-nous sur : Serveur de fichiers [NAS] Le Tableau de bord projets Le groupe de travail ICMO

  17. #17
    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
    Points : 13 017
    Points
    13 017
    Par défaut
    Citation Envoyé par Jean-Marc.Bourguet Voir le message
    J'ai deja trois niveaux facilement pour les membres d'un objet:
    - pas thread-safe du tout (depend qu'une variable globale non protegee ne soit pas modifiee par exemple)
    - thread safe tant qu'on l'appelle sur des objets differents (elle modifie l'objet mais celui-ci n'est pas protege par un mutex, c'est ce que fournissent classiquement les implementations de la SL "thread-safe")
    - thread safe meme quand on l'appelle sur le meme objet (elle se contente de lire des informations ou elle fait des modifications en se protegeant)

    Et comme je l'ai dit, des qu'il y a plus d'un membre, il faut aussi definir les interractions entre eux (par exemple les membres faisant uniquement de la lecture sont compatibles entre eux sur un meme objet mais pas avec ceux qui le modifient)
    Je crois que c'est dans Qt qu'il font cette différence :
    - une classe pas thread-safe du tout : comme toi : l'appel concurrent pose problème.
    - une classe thread safe : on peut appeler n'importe quelle méthode de la classe dans différents threads sur le même objet
    - une classe réentrante : on peut appeler n'importe quelle méthode de la classe dans différents (ou pas) threads sur différents objets.

    Bref, thread-safe est définie dans le contexte d'un même objet et réentrante pour des objets différents.
    Du coup, les 2 notions sont séparées. Et thread-safe garde un sens assez proche avec une classe et avec une fonction libre.

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

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Dans .Net, la plupart des classes suit la définition de Jean-Marc.Bourguet:
    Citation Envoyé par MSDN
    Thread Safety
    Public static (Shared in Visual Basic) members of this type are thread safe. Any instance members are not guaranteed to be thread safe.
    Quant aux histoires de réentrance, il faut considérer plusieurs cas:
    • Appel de la fonction alors qu'elle s'exécute déjà dans le même thread (fonction s'appelant elle-même, ou appelant un callback)
    • Fonction avec contexte non-accessible à l'appelant (comme les fonctions dites "non-réentrantes" du C, qui ont un contexte en variable globale ou statique).
    • Fonction avec contexte accessible à l'appelant (comme les version dites "réentrantes" des fonctions dites "non-réentrantes" du C).

    Après, il faut voir dans quel cas "this" compte comme contexte ou non...
    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.

  19. #19
    Expert éminent sénior
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 275
    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 275
    Points : 10 985
    Points
    10 985
    Par défaut
    Citation Envoyé par 3DArchi Voir le message
    Ben, c'est [les mutex] certainement la première solution aux race conditions mais qu'on a du mal à bien appréhender les conséquences et notamment les scénarii de deadlock qui en découlent. Mais je comprend mieux ta remarque sur le TLS. L'objectif est d'éliminer les dépendances entre les différentes tâches de façon à ne pas avoir à utiliser les mécanismes de lock.

    Il y en a tout une palanqué ici et ici. Tu penses auquel ?
    C'est la première solution qu'on nous enseigne.
    La première à laquelle je pense aujourd'hui, c'est comment faire ça avec des tâches (à la ACE) qui s'échangent des messages ?
    La deuxième, est "un compteur atomique ?"
    La troisième, est "et avec un TLS ?"
    Et en dernier lieu je finis sur "bon ben mutex hiérarchisés/hiérarchisables "
    Je n'ai pas encore bien assimilé la copie d'états pour éviter à les partager. Je sais que cela existe, mais ce n'est pas encore un réflexe.

    Pour ma remarque sur les TLS, c'est parce qu'avec eux il est facile de faire du MT-safe, non réentrant.

    Pour les articles, je pensais à ceux de sa colonne sur le DDJ.
    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...

  20. #20
    Inactif  
    Avatar de Mac LAK
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    3 893
    Détails du profil
    Informations personnelles :
    Âge : 49
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Octobre 2004
    Messages : 3 893
    Points : 4 846
    Points
    4 846
    Par défaut
    Citation Envoyé par Luc Hermitte Voir le message
    Pour ma remarque sur les TLS, c'est parce qu'avec eux il est facile de faire du MT-safe, non réentrant.
    Du réentrant aussi, via deux TLS... Le premier est un compteur atomique de réentrance, le second un pointeur vers une liste de contextes détruits après traitement, en mode FIFO ou LIFO en fonction du type de réentrance choisi (LIFO en général, d'ailleurs...).

    Au besoin, un troisième TLS pour définir un numéro d'ordre, en cas de traitement long et de scheduling complexe, et t'as une fonction réentrante.
    Mac LAK.
    ___________________________________________________
    Ne prenez pas la vie trop au sérieux, de toutes façons, vous n'en sortirez pas vivant.

    Sources et composants Delphi sur mon site, L'antre du Lak.
    Pas de question technique par MP : posez-la dans un nouveau sujet, sur le forum adéquat.

    Rejoignez-nous sur : Serveur de fichiers [NAS] Le Tableau de bord projets Le groupe de travail ICMO

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

Discussions similaires

  1. Programmation par contrat en C++
    Par bolhrak dans le forum C++
    Réponses: 11
    Dernier message: 07/09/2007, 00h12
  2. [Language]Programmation par contrat
    Par manube dans le forum Langage
    Réponses: 3
    Dernier message: 20/12/2005, 10h16
  3. [Eiffel] Programmation par contrats
    Par SkIllz2k dans le forum Autres langages
    Réponses: 1
    Dernier message: 02/05/2005, 20h05
  4. [Tests]La programmation par contrats
    Par fabien.raynaud dans le forum Test
    Réponses: 6
    Dernier message: 26/07/2004, 11h06

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