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

SL & STL C++ Discussion :

std::atomic<T*> : pas d'opérateur -> ?


Sujet :

SL & STL C++

  1. #1
    Membre chevronné

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juin 2007
    Messages
    373
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Royaume-Uni

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

    Informations forums :
    Inscription : Juin 2007
    Messages : 373
    Par défaut std::atomic<T*> : pas d'opérateur -> ?
    Bonjour,

    Je découvre actuellement les joies de la programmation concurrente, et suis tombé sur un bel article faisant usage de std::atomic<T*> pour créer une file thread safe et sans lock.

    Dans cet article justement, l'auteur (Herb Sutter) utilise le type std::atomic<T*> comme s'il s'agissait d'un pointeur normal, c'est à dire en substance :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    struct node {
        node* next;
    };
    std::atomic<node*> some_node = ...;
    some_node = some_node->next;
    Or, j'ai beau regarder dans mon implémentation (GCC 4.7) et sur les sites décrivant la nouvelle norme C++11 (click), il n'est fait mention nulle part que std::atomic<T*> dispose d'un T* operator -> () (i.e. le code ci-dessus génère une erreur à la ligne 5).

    J'ai donc deux questions :
    • Sutter fume-t-il de l'herbe ?
    • Pourquoi cet opérateur n'est-il pas ajouté à la spécialisation de std::atomic<T> pour T = U* ?


    Si vous connaissez la réponse à la seconde (la première m'intéresse moins), je suis intéressé.

  2. #2
    Inactif  


    Homme Profil pro
    Inscrit en
    Novembre 2008
    Messages
    5 288
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Secteur : Santé

    Informations forums :
    Inscription : Novembre 2008
    Messages : 5 288
    Par défaut
    Tu n'es pas le seul, d'autre personnes font la remarque dans les commentaires que le code n'est pas compilable.
    L'article date de 2008, donc probablement pas compilé avec gcc 4.7 (et donc pré-norme). Peut être qu'il utilisait une implémentation personnelle de atomic avec des features qui n'ont pas été conservé par la suite ?

  3. #3
    Membre chevronné

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juin 2007
    Messages
    373
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Royaume-Uni

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

    Informations forums :
    Inscription : Juin 2007
    Messages : 373
    Par défaut
    Ils parlent d'un autre soucis dans les commentaires, qui a été corrigé depuis : le fait d'écrire <node> perturbait le code de mise en forme du site. Mais je suis d'accord avec toi sur le fait qu'il doit s'agir d'une implémentation maison.

    Ma seconde question demeure toutefois : pour quelle raison cet opérateur bien pratique est-t-il absent ? On peut contourner le problème en écrivant (*some_node).next à la place, mais ce n'est pas très élégant.

  4. #4
    Inactif  


    Homme Profil pro
    Inscrit en
    Novembre 2008
    Messages
    5 288
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Secteur : Santé

    Informations forums :
    Inscription : Novembre 2008
    Messages : 5 288
    Par défaut
    /mode pêche aux devinettes

    Petite réflexion. Quand tu écris
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    std::atomic<node*> some_node = ...;
    Le pointeur est atomic, mais par contre, l'objet pointé ne l'ai pas (je pense). Du coup *some_node n'est pas atomic et l'écriture some_node->next est peut être confuse (puisque l'on peut penser que le type est atomic alors que ce n'est pas le cas)
    Du coup, un tel code n'est pas safe :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    some_node->next = another_node;
    Par contre, le code de Herb :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    some_node = some_node->next;
    est safe, puisque l'on transforme le type non atomic some_node->next en atomic

  5. #5
    Membre éprouvé
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 766
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 766
    Par défaut
    Dans l'ancienne norme, l'opérateur flèche sur les éléments de conteneur n'étaient pas spécifié, même si de nombreux compilateurs le fournissaient.

    Peut-être est-ce par souci de cohérence ?

  6. #6
    Membre chevronné

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juin 2007
    Messages
    373
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Royaume-Uni

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

    Informations forums :
    Inscription : Juin 2007
    Messages : 373
    Par défaut
    Oui, je n'ai a vrai dire pas fait attention à la sémantique ici, juste à la forme. Il se trouve que *some_node est un raccourcis d'écriture pour some_node.load(), qui est une opération atomique (mais effectivement, les opérations sur la valeur pointée n'ont aucune garantie d'atomicité).

    l'écriture some_node->next est peut être confuse (puisque l'on peut penser que le type est atomic alors que ce n'est pas le cas)
    Moui, c'est aussi le cas de (*some_node).next, même si le fait que ce soit une syntaxe inhabituelle peut mettre la puce à l'oreille.

    Dans l'ancienne norme, l'opérateur flèche sur les éléments de conteneur n'étaient pas spécifié, même si de nombreux compilateurs le fournissaient.
    Tu veux dire en C++03 ? En tout cas c'est bel et bien spécifié dans la norme actuelle (cf. 13.5.6), or c'est dans celle-ci qu'a été introduit std::atomic.

  7. #7
    Membre éprouvé
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 766
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 766
    Par défaut
    Citation Envoyé par Kalith Voir le message
    Tu veux dire en C++03 ? En tout cas c'est bel et bien spécifié dans la norme actuelle (cf. 13.5.6), or c'est dans celle-ci qu'a été introduit std::atomic.
    Je n'ai pas été assez clair. Je parlais en fait des itérateurs. L'opérateur flèche n'était pas spécifié pour les itérateurs, il me semble. En tout cas, pour C++11, il n'est défini que pour les itérateurs d'entrée.

  8. #8
    Membre chevronné

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juin 2007
    Messages
    373
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Royaume-Uni

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

    Informations forums :
    Inscription : Juin 2007
    Messages : 373
    Par défaut
    Citation Envoyé par oodini Voir le message
    Je n'ai pas été assez clair. Je parlais en fait des itérateurs. L'opérateur flèche n'était pas spécifié pour les itérateurs, il me semble. En tout cas, pour C++11, il n'est défini que pour les itérateurs d'entrée.
    Ah ! Pardon, j'avais mal compris. J'ai regardé plus en détail, l'opérateur en question est effectivement défini pour les input_iterator, et de fait pour tous les autres types d'itérateurs (à l'exception des output_iterator), puisqu'ils héritent des propriétés de input_iterator.
    Dans ce cas précis, ça a un sens : on est pas sensé lire le contenu d'un output_iterator, mais on peut écrire quelque chose dedans :
    "Output iterators are iterators especially designed for sequential output operations, where each element pointed by the iterator is written a value only once and then the iterator is incremented."
    Citation Envoyé par oodini Voir le message
    Cela dit, il n'est guère étonnant que cela n'existe pas de manière générique pour atomic, car il n'aurait de sens que pour des spécialisations par pointeur.
    De manière générique je suis tout à fait d'accord. Mais le fait est que le standard impose une spécialisation de std::atomic pour les pointeurs : ajouter cette fonctionnalité ne représente qu'une ligne de code supplémentaire. Donc soit c'est un oubli, soit il y a une véritable raison pour ne pas le faire (et j'aimerai bien savoir laquelle).

  9. #9
    Membre Expert

    Inscrit en
    Mai 2008
    Messages
    1 014
    Détails du profil
    Informations forums :
    Inscription : Mai 2008
    Messages : 1 014
    Par défaut
    Citation Envoyé par Kalith
    Donc soit c'est un oubli, soit il y a une véritable raison pour ne pas le faire (et j'aimerai bien savoir laquelle).
    La raison donnée par gbdivers m'a l'air convaincante, non ?

    Quand on regarde l'interface de std::atomic tous les opérateurs fournies, sans aucune exception, garantissent l'atomicité de l'opération en question (operator++, operator= etc). Maintenant si l'on ajoute l'opérateur -> alors on aurait une exception flagrante à cette règle, vu qu'on ne peut pas garantir l'atomicité de l'utilisation de ->. Donc je pense que la raison principale est une raison d'uniformité. On veut pouvoir dire : toutes les opérations proposées par std::atomic sont atomiques, sans exception.

    D'ailleurs, lorsqu'on regarde les deux écritures :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    some_node->next
    (*some_node).next
    la deuxième offre l'avantage de bien montrer les deux opérations distinctes :

    (*some_node) : opérateur de déréférencement faisant parti de l'interface de std::atomic : atomicité garantie.

    (...).next : utilisation de euuu, je ne connais pas vraiment son nom, l'opérateur "d'accès aux champs de la structure" peut être, qui appartient cette fois au type node, donc aucune atomicité n'est garantie.

  10. #10
    Membre chevronné

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juin 2007
    Messages
    373
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Royaume-Uni

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

    Informations forums :
    Inscription : Juin 2007
    Messages : 373
    Par défaut
    Oui c'est une explication plausible... mais discutable.

    L'atomicité de std::atomic ne s'applique qu'à la valeur de l'objet encapsulé, c'est à dire ici à l’adresse stockée par le pointeur. Une fois qu'on a chargé de manière atomique cette adresse dans un registre du processeur, on en fait ce qu'on veut : tant qu'on ne lis/modifie pas la valeur (du pointeur, pas de l'objet sous-jacent) stockée dans la RAM, le contrat d'atomicité sur la valeur du pointeur est respecté. Or l'opérateur -> modifie potentiellement l'objet, mais jamais le pointeur. Il fait une seule lecture, et on est assuré qu'elle est atomique.

    Donc à mon sens, l'utilisation de -> est atomique du point de vue du pointeur encapsulé. N'est-ce pas ce qui compte ?

  11. #11
    Inactif  


    Homme Profil pro
    Inscrit en
    Novembre 2008
    Messages
    5 288
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Secteur : Santé

    Informations forums :
    Inscription : Novembre 2008
    Messages : 5 288
    Par défaut
    J'ai recherché s'il y avait eu une discussion sur le sujet, mais j'ai rien trouvé. Il serait peut être intéressant de profiter du fait que le comité de normalisation a créé des forums de discussions sur la norme (http://www.developpez.net/forums/d12...alisation-cpp/) pour leur poser la question.

    C'est effectivement discutable. Mais j'ai surtout l'impression que c'est une question de choix de design et que donc, tout le monde ne sera pas forcement d'accord. D'autant plus que, comme l'opérateur n'est pas explicitement interdit dans la norme, cela veut dire qu'un compilateur peut l'ajouter s'il le souhaite... ça pourrait effectivement être perturbant

  12. #12
    Membre chevronné

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juin 2007
    Messages
    373
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Royaume-Uni

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

    Informations forums :
    Inscription : Juin 2007
    Messages : 373
    Par défaut
    C'est une bonne idée : lien vers la discussion sur google groups.
    C'est la première fois que je poste là bas, j'espère n'avoir pas enfreint une centaine de règles d'étiquette...

  13. #13
    Inactif  


    Homme Profil pro
    Inscrit en
    Novembre 2008
    Messages
    5 288
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Secteur : Santé

    Informations forums :
    Inscription : Novembre 2008
    Messages : 5 288
    Par défaut

Discussions similaires

  1. [C++] Trier un std::map par clé => fonctionne pas
    Par Aspic dans le forum C++/CLI
    Réponses: 2
    Dernier message: 28/12/2013, 16h18
  2. Réponses: 1
    Dernier message: 31/07/2012, 18h53
  3. std::cout pourquoi n'affiche pas le message
    Par loisir1976 dans le forum Débuter
    Réponses: 4
    Dernier message: 10/05/2010, 00h32
  4. Réponses: 10
    Dernier message: 30/06/2008, 19h59
  5. erreur : "pas d'opérateur de tri"
    Par wonderyan dans le forum Langage SQL
    Réponses: 9
    Dernier message: 07/01/2008, 15h20

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