D'accord, je demande la même chose que Cette question supprimée , mais je le demande plus directement. p>
J'ai deux variables de pointeur dans deux cas de la même classe. Je voudrais échanger le contenu de ces variables (pas ce qu'ils indiquent, juste les variables elles-mêmes) atomique. P>
J'aimerais éviter les serrures si possible. P>
Comment puis-je faire cela? P>
sur le registre de la pile s>. (Par lui-même) n'échange pas deux pointeurs dans des emplacements de mémoire. P>
3 Réponses :
Je vais sortir sur un membre et dire que vous avez besoin d'une serrure et qu'il n'y a pas de solution sans verrouillage général à ce problème. p>
Vous auriez besoin de lire à partir de deux adresses et d'écrire aux deux adresses toutes atomiquement. Au mieux de mes connaissances, X86 ne peut échanger atomiquement des données d'une seule adresse mémoire et d'un registre. Je ne pense pas qu'il soit possible d'échanger le contenu de deux adresses de mémoire. P>
Si vous pouvez mettre des contraintes sur l'endroit où les pointeurs sont, vous pouvez le faire. Par exemple, si vous pouvez garantir que les pointeurs sont adjacents en mémoire, vous pouvez utiliser un comparateur / échange de 64 ou 128 bits dans une boucle. P>
Il peut y avoir des solutions pour d'autres cas simples, mais je ne pense pas que vous allez trouver une solution sans verrouillage pour le cas général. P>
+1 - ressemble à aucun windowsapi :: autoparray :: échange code> Sécurité du fil pour moi. ('Parce que chaque pointeur ne justifie pas les frais généraux du maintien d'une section critique!)
Une sélection limitée de processeurs dispose d'une double opération de comparaison et d'échange (DCAS / CAS2). Vous pouvez également utiliser CMPXCHG16B (double largeur) à un effet similaire. Ce n'est pas "général" dans ce que de nombreux processeurs ne supporte pas ces instructions, mais sur ceux qui le font peuvent être effectués. Dcas se trouve sur Motorola 68K, CMPXCHG16B est sur 64 bits Intel et Newer i> AMD 64 bits, mais pas plus vieux. _InterlockedconeExchange1Change128 Implémente ceci comme une matrice de points de 64 bits évalués sous forme de champ atomique 128 bits, mais explosera si le processeur ne prend pas en charge l'instruction.
Vérifiez les instructions XCLG du processeur X86 si elles font ce que vous voulez, vous pouvez les envelopper dans la fonction d'assemblage en ligne. Tous les instructions simples du processeur sont garantis pour être atomiques. P>
Cette réponse a les mêmes problèmes que les réponses de InterverockedExchangeVointer.
+1 parce que le si i> dans si ils font ce que vous voulez i> retourne faux, vous n'allez donc pas trouver un moyen simple de faire cela
@Pete: si i> que "si" revient faux, alors cela ne répondit pas ma question, même si ce n'est pas factuellement incorrect.
@Billy: Je suis d'accord. @Gene a fondamentalement dit "Je n'ai aucune idée, mais jette une fléchette au manuel et si elle frappe quelque chose que vous pouvez utiliser, c'est ce que vous devez utiliser." C'est idiot à +1 cette réponse.
Je suis à peu près sûr que la déclaration "Tous les instructions simples du processeur sont garantis pour être atomiques" est faux. Cela pourrait être vrai, mais sur x86, je doute très sincèrement.
Vous recherchez une version atomique et verrouillée de À ma connaissance, il n'y a aucun moyen de le faire en utilisant uniquement les primitives de l'API Windows et aucun verrouillage explicite. Les diverses fonctions code> code> recommandées par d'autres ne fonctionneront pas car un seul des paramètres transcédés est modifié. Vous voulez les changer à la fois. P>
Je pourrais également indiquer que les fonctions Autant que je sache, vous devrez utiliser une bibliothèque ou écrire votre propre code pour gérer cela. P> échange code>. p>
en verrouillées code> ne sont que verrouillées les unes aux autres. Si vous avez un autre morceau de code qui met à jour l'un de ces pointeurs mais n'utilise pas interclocké code>, votre code n'est plus en sécurité. Je suis sûr que vous réalisez cela, mais je pensais en parler. P>
Je ne pense pas qu'il existe une instruction X86 non verrouillée pour échanger le contenu de deux adresses de mémoire. Sans soutien de la CPU, il serait difficile de mettre en œuvre une telle fonction. Y a-t-il des garanties sur les pointeurs? (E.G., sont-ils toujours adjacents en mémoire? Dans l'affirmative, vous pouvez utiliser un comparatif / échange de 8 octets ou de 16 octets dans une boucle.)
@James: Depuis que vous avez posté la même chose sur le commentaire de chacun:
Int * P1 = Quel qu'envalue; int * p2 = quelque ouverture; P2 = InterlockedExchangeVointer (P1, P2); Code> ferait exactement cela. Cependant, sous elle utilise une section critique, je ne suis donc pas sûr que cela correspond parfaitement à la nécessité d'éviter complètement les serrures.Wow, beaucoup de gens donnant la mauvaise réponse ... Cela devrait être une question d'entrevue
: -) code>Et que le diable commence à upvoter les mauvaises réponses?
@ZAC: Non, ce ne sera pas.
InterlockedExchangeVointer Code> prend l'adresse d'un pointeur et du pointeur pour stocker à cette adresse. Il faudrait deux appels versInterlockedExchangeVointer Code> pour échanger les valeurs de deux pointeurs et, tandis que chaque appel à une fonction code> interclocké > est atomique, deux appels ne sont pas ensemble atomiques.@Billy: "... avec une valeur sur la pile." Il n'y a absolument aucune mention de la pile nulle part dans les documents. Où as-tu tiré ça? Est-ce que vous i> lisez les docs?
@James: Je suis corrigé. Je lisais la documentation pour signifier que vous pouvez utiliser la valeur de retour pour effectuer le swap sans penser que l'attribution de copie pour le deuxième pointeur ne serait pas verrouillée.
@ZAC, @gimpf: Et son fil-danger.
@OJ: C'est un paramètre de fonction, Ergo, ça se passe sur la pile. @James 'Le point est que dans la fonction, il vient de la pile, ce qui est probablement vrai.
@Billy: Ouais. Techniquement, la valeur du pointeur pourrait être n'importe où que le compilateur veuille le mettre. Sur X86, je suis presque positif qui doit être dans un registre. Je ne suis pas un expert X86 cependant, pourquoi je n'ai été que des personnes pesantes via des commentaires au lieu de répondre à la question suivante :-)
@James: Oui, l'instruction ne fonctionne qu'avec un emplacement de mémoire et deux registres.
Je ne comprends pas ... Ces pointeurs sont-ils tous deux lus dans une lecture atomique? Sinon, cela ne devrait pas imaginer si votre échange est atomique ou non.
@Chris: Comme indiqué, il demande une mise en œuvre atomique et sans verrouillage de
swap (vide * &, vide * &) code>.@Chris: Il a deux pointeurs. Il veut lire à partir du pointeur 1, lu depuis le pointeur 2, écrivez la valeur au pointeur 2 au pointeur 1 et écrivez la valeur au pointeur 1 au pointeur 2. tous atomiquement.
@james, @ wj32: Je sais ce qu'il veut. Mon point était que sans la capacité de les lire atomiquement, il n'est pas nécessaire de les échanger à la fois atomiquement, car les chemins d'exécution éventuels sont fondamentalement les mêmes que vous utilisez ou non un échange atomique.
@Chris: Cela n'a aucun sens. Considérez deux threads échangeant avec la même valeur. Le fil 1 lit la valeur, le fil 2 lit la valeur, le fil 2 écrit sa nouvelle valeur, le fil 1 écrit la nouvelle valeur. Résultat: le tampon précédemment tenu par le fil 2 est divulgué.
@Billy: Oui, j'ai réalisé après que je lui ai demandé que cet échange atomique lui-même lit atomique les deux valeurs.