2010-09-17 25 views
7

Je tente d'implémenter la bibliothèque atomique à partir du brouillon C++ 0x. Plus précisément, je suis mise en œuvre §29.6/8, le magasin méthode:Implémentation de l'atomique <T> :: store

template <typename T> 
void atomic<T>::store(T pDesired, memory_order pOrder = memory_order_seq_cst); 

Les états d'exigence:

L'argument de l'ordre ne doit pas être memory_order_consume, memory_order_acquire, ni memory_order_acq_rel.

Je ne sais pas quoi faire si c'est l'un d'entre eux. Devrais-je ne rien faire, lancer une exception, obtenir un comportement indéfini ou faire autre chose?

P.S .: "C++ 0X" ressemble un peu comme un poisson mort: 3

+7

+1 pour un poisson mort. – GManNickG

Répondre

9

Faites ce que vous voulez. Cela n'a pas d'importance.

Lorsque l'ISO déclare que vous "ne devez pas faire quelque chose", le faire est un comportement indéfini. Si un utilisateur fait cela, ils ont violé le contrat avec la mise en œuvre, et la mise en œuvre est dans son droit de faire ce qu'il veut.

Ce que vous décidez de faire dépend entièrement de vous. J'opterais pour ce qui rendrait votre implémentation "meilleure" (à vos yeux, soyez plus rapide, plus lisible, sujet au principe du moindre étonnement, et ainsi de suite).

Moi, j'irais pour la lisibilité (puisque je devrais maintenir la chose) avec la vitesse en prenant une seconde près.

0

Je préfère obtenir un comportement vaguement sain que quelque chose de fou. Eh bien, en tant que consommateur potentiel de votre bibliothèque, voici ce que je voudrais: s'il n'y a pas de coût de performance pour l'utilisation documentée, alors voir si l'une des valeurs memory_order fournit un surensemble fonctionnel des autres, en particulier quelque chose correspondant à quoi un appelant pourrait naïvement s'attendre à ce que les modes non supportés fassent (si une attente raisonnable peut être formée). L'appelant peut obtenir le mode le plus lent et le plus sûr, mais c'est mieux que quelque chose de mal fonctionnellement. Vous réduisez la dépendance du code client à ce que tout soit parfait pour votre code. Le problème avec ceci - comparé à un assert/exception - est qu'il peut passer inaperçu dans un environnement de test, donc considérez également écrire une explication à std :: cerr, en utilisant une variable statique pour limiter les messages à un par processus. C'est un diagnostic très utile. Une exception, une assertion fatale, etc. peut faire tomber une application client à un moment très incommode ... Cela semble un peu draconien, et pas quelque chose que j'apprécierais particulièrement. Une autre option consiste à avoir une variable d'environnement qui contrôle ce comportement.

(Il y a probablement un problème similaire pour les valeurs qui ne sont même pas dans votre énumération actuelle.)

+3

Si vous comptez sur un comportement indéfini, je préférerais que mon implémentation reformate votre disque dur (ce qui est en fait un comportement valide). C'est parce que, pendant que vous le récupérez, vous n'allez pas pousser le code bogué :-) Il peut y avoir un mauvais comportement fonctionnel si ce n'est pas défini, c'est ce que signifie "non défini". – paxdiablo

+0

@paxdiablo. Quelle déclaration inutile. Comportement indéfini est généralement invoqué accidentellement, d'où la question en premier lieu. Grandir. C'est ce qu'on appelle la «programmation défensive», et j'en ai marre de tous les types de contrat par contrat agissant comme de mauvais garçons. –

+3

Ce que vous préférez obtenir n'est pas pertinent. La norme stipule que vous n'êtes pas autorisé à le faire pour que l'implémenteur soit libre de faire ce qu'il veut. Ils peuvent choisir de le gérer avec élégance ou ils peuvent (et c'est ma préférence) juste l'ignorer et vous pouvez réparer votre propre code. Je ne suis pas là pour vous rendre si vous enfreignez les règles. Ce n'est pas différent pour les gens qui se plaignent du fait que 'i = ++ i + i ++;' ne fonctionne pas comme prévu - la réponse est _don't pas le faire! _ Et, si c'était vous -1'ed ma réponse (hypothèse de ma part mais probablement correcte compte tenu de votre ton), je suppose que je suis assez "adulte" pour ne pas riposter. – paxdiablo

0

Je préfère une erreur de compilation. Si ce n'est pas le cas, alors un assert() échoue. Assert est bon car il compile à partir de la version et n'affecte pas les performances.

Les erreurs de temps de compilation sont encore meilleures car elles fournissent un retour d'information plus immédiat sans attendre que le logiciel trébuche sur le bogue. Les vérifications des erreurs de compilation sont une chose que j'aime à propos du code C++ sur Python, Ruby, le code Perl.