34 votes

Alors que la boucle avec le corps vide vérifie les éléments volatils - qu'est-ce que cela signifie?

Je regarde une classe C ++ qui a les lignes suivantes:

 while( x > y );
return x - y;
 

x et y sont des variables membres de type volatile int . Je ne comprends pas cette construction.

J'ai trouvé le stub de code ici: https://gist.github.com/r-lyeh/cc50bbed16759a99a226 . Je suppose que ce n'est pas garanti d'être correct ou même de travailler.

62voto

therainmaker Points 3185

Depuis x et y ont été déclarés comme volatile, le programmeur s'attend à ce que ils vont être modifiés à partir de l'extérieur du programme.

Dans ce cas, votre code restera dans la boucle

 while(x>y);

et sera de retour la valeur x-y d'après les valeurs sont modifiées à partir de l'extérieur tels que x <= y. La raison exacte de ce qui est écrit peut être deviné après vous nous en dire plus sur votre code et où vous l'avez vu. L' while boucle dans ce cas est en attente de la technique pour un autre événement de se produire.

25voto

Stas Points 3333

Il semble

while( x > y );

est une filature de la boucle. Il ne s'arrêtera pas jusqu' x <= y. En tant que x et y sont volatile, ils peuvent être modifiés en dehors de cette routine. Donc, une fois x <= y devient true, x - y sera retourné. Cette technique est utilisée pour attendre un événement.

Mise à jour

Selon le résumé que vous avez ajouté, il semble que l'idée était de mettre en œuvre thread-safe lock-gratuit tampon circulaire. Oui, l'application est incorrecte. Par exemple, le code original-extrait de

unsigned count() const {
    while( tail > head );
    return head - tail;
}

Même si tail devient inférieur ou égal à head, il n'est pas garanti qu' head - tail renvoie un nombre positif. Le planificateur peut changer d'une exécution à une autre thread immédiatement après l' while boucle, et le thread peut changer en head de la valeur. De toute façon, il y a beaucoup d'autres questions liées à la façon dont la lecture et l'écriture à la mémoire partagée de travail (réorganisation de la mémoire, etc.), donc, ignorez simplement ce code.

20voto

Syren Baran Points 399

D'autres réponses ont déjà fait observer dans le détail ce que l'instruction n', mais juste pour faire un rappel que, depuis y (ou head dans les liens exemple) est déclaré comme volatile modifications apportées à cette variable à partir d'un autre thread sera la cause de la while boucle pour en finir une fois la condition a été remplie.

Cependant, même si le lié exemple de code est très court, c'est un exemple quasi parfait de comment ne PAS écrire de code.

Tout d'abord la ligne

while( tail > head );

de déchets d'énormes quantités de cycles de CPU, un peu de verrouillage en place d'une base jusqu'à ce que la condition a été remplie.

Le code est encore meilleure que nous allons.

buffer[head++ % N] = item;

Grâce à JAB pour souligner je me suis trompé de post - pré-incrémentation ici. Corrigé les implications. Depuis il n'y a pas d' locks ou mutexes de toute évidence, nous devrons supposer le pire. Le fil de l'interrupteur après l'affectation de la valeur en item et avant head++ s'exécute. Murphy sera alors appeler la fonction contenant cette déclaration à nouveau, de l'affectation de la valeur de item à de même head position. Après qu' head par incréments. Maintenant nous revenir à la première thread et d'incrément head de nouveau. Ainsi, au lieu de

buffer[original_value_of_head+1] = item_from_thread1; 
buffer[original_value_of_head+2] = item_from_thread2;

nous nous retrouvons avec

buffer[original_value_of_head+1] = item_from_thread2; 
buffer[original_value_of_head+2] = whatever_was_there_previously;

Vous pourriez sortir avec bâclée codage de ce genre sur le côté client avec quelques fils, mais du côté serveur, et ce ne pouvait être considéré comme une bombe à retardement. Veuillez utiliser la synchronisation des constructions telles que locks ou mutexes à la place.

Et bien, juste pour le plaisir de l'exhaustivité, de la ligne

while( tail > head );

dans la méthode de pop_back() devrait être

while( tail >= head );

sauf si vous voulez être en mesure de pop un élément de plus que vous avez réellement poussé (ou même pop un élément avant de le pousser quoi que ce soit dans).

Désolé pour l'écriture de ce qui fondamentalement se résume à une longue diatribe, mais si ça continue, une seule personne, à partir de la copie et de collage qui obscène code qu'il valait la peine.

Mise à jour: la Pensée que je pourrais donner un exemple où un code comme celui - while(x>y); en fait tout à fait logique. En fait, vous avez l'habitude de voir le code tel qu'assez souvent dans le "bon vieux" jours. la touxDOS. N'était pas utilisé dans le contexte d'enfiler bien. Principalement comme une solution de repli dans le cas de l'enregistrement d'un crochet d'interruption n'a pas été possible (vous, les enfants pourrait traduire ainsi: "pas possible d'enregistrer un gestionnaire d'événement").

startAsynchronousDeviceOperation(..);

Qui pourrait être beaucoup de choses, par exemple, dites-le disque dur pour lire les données via DMA, ou de dire à la carte son pour enregistrer via DMA, peut-être même appeler des fonctions sur un processeur différent (comme le GPU). Généralement initiées par quelque chose comme outb(2).

while(byteswritten==0); // or while (status!=DONE);

Si le seul canal de communication avec un périphérique de mémoire partagée, alors ainsi soit-il. Pas s'attendre à voir le code comme ça de nos jours en dehors des pilotes de périphérique et les microcontrôleurs bien. Suppose bien entendu que les spécifications de l'état à cet emplacement de mémoire est le dernier écrit à.

7voto

Olipro Points 953

L' volatile mot-clé est conçu pour prévenir certaines optimisations. Dans ce cas, sans le mot clé, le compilateur pourrait dérouler votre while boucle en béton séquence d'instructions qui cassera évidemment, en réalité, puisque les valeurs susceptibles d'être modifiées à l'extérieur.

Imaginez le suivant:

int i = 2;
while (i-- > 0) printf("%d", i);

La plupart des compilateurs regarder cela et il suffit de générer deux appels d' printf - ajout de l' volatile mot-clé, il au lieu de générer des instructions du PROCESSEUR qui font appel à un ensemble de compteurs à 2 et un contrôle sur la valeur après chaque itération.

Par exemple,

volatile int i = 2;
this_function_runs_on_another_process_and_modifies_the_value(&i);
while(i-- > 0) printf("%d", i);

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X