__sync_val_compare_and_swap vs __sync_bool_compare_and_swap

Habe ich mir Gedanken über die return-Werte dieser beiden Funktionen. Die __sync_bool_compare_and_swap-Funktion den Rückgabewert zu haben scheint offensichtliche Vorteile, also kann ich es verwenden, um zu sagen, ob die swap-operation stattfand. Allerdings kann ich nicht sehen, einen guten Gebrauch von __sync_val_compare_and_swap Rückgabewert.

Erstens, können eine Funktion Signatur-Referenz (von GCC-docs minus die var args):

type __sync_val_compare_and_swap (type *ptr, type oldval type newval);

Das problem, das ich sehe, ist, dass der Rückgabewert von __sync_val_compare_and_swap ist der alte Wert von der *ptr. Um genau zu sein, ist es das Wert gesehen wurde, durch die Implementierung dieser Funktion einmal geeignete Speicher Barrieren war geschaffen worden. Ich hätten dies ausdrücklich zu bieten für die Tatsache, dass die zwischen den aufrufenden __sync_val_compare_and_swap und ausführen von Anweisungen, um die Durchsetzung der memory-Barriere der Wert von *ptr könnte leicht ändern.

Nun, wenn die Funktion zurückgibt, was kann ich tun, mit diesem return-Wert? Es gibt keinen Sinn, zu versuchen, zu vergleichen mit *ptr, da *ptr können jetzt geändert werden, in anderen threads. Ebenso vergleichen newval und *ptr nicht wirklich helfen (es sei denn, ich Sperre *ptr, die wahrscheinlich untergräbt meine Verwendung von atomics in den ersten Platz).

Also alle, die wirklich Links für mich zu tun, ist zu Fragen, ob der Rückgabewert == oldval, das ist effektiv (siehe unten für eine Einschränkung) mit der Frage, ob die swap-operation stattfand. So konnte ich gerade benutzt haben __sync_bool_compare_and_swap.

Dem VORBEHALT, ich habe gerade erwähnt, dass das nur subtiler Unterschied, den ich hier sehen kann, ist, dass dies nicht mir sagen, ob die swap aufgetreten ist oder nicht, es sagt mir nur, dass irgendwann, bevor die memory-Barriere wurde freigegeben *ptr hatte den gleichen Wert wie newval. Ich überlege mir die Möglichkeit, oldval == newval (obwohl ich würde kämpfen, um zu sehen, eine Art und Weise der Umsetzung, die effizient funktionieren, so dass Sie überprüfen könnten, diese Werte zuerst und nicht tauschen, wenn Sie waren die gleichen also ist es wohl ein strittiger Punkt). Allerdings kann ich nicht sehen, eine situation, wo die Kenntnis dieser Unterschied würde einen Unterschied machen, um mich an der call-site. In der Tat, ich kann mir nicht vorstellen, eine situation, wo ich würde oldval und newval gleich zu sein.

Meine Frage ist also:

Gibt es irgendeinen Anwendungsfall, in dem mit __sync_val_compare_and_swap und __sync_bool_compare_and_swap wäre nicht gleichwertig, d.h. ist es eine situation, wo man mehr Informationen als die anderen?

BEISEITE

Der Grund, warum ich war über dieses denken war, das fand ich eine Implementierung des __sync_val_compare_and_swap in Bezug auf sync_bool_compare_and_swap, die eine Rasse:

inline int32_t __sync_val_compare_and_swap(volatile int32_t* ptr, int32_t oldval, int32_t newval)
{
    int32_t ret = *ptr;
    (void)__sync_bool_compare_and_swap(ptr, oldval, newval);
    return ret;
}

Die Rasse wird zur Speicherung von *ptr ret, *ptr könnte sich ändern, vor __sync_bool_compare_and_swap genannt wird. Es machte mir klar, dass ich es nicht scheinen, um einen sicheren Weg (ohne zusätzliche Barrieren oder sperren) Umsetzung __sync_val_compare_and_swap in Bezug auf sync_bool_compare_and_swap. Das gab mir zu denken, dass die ehemaligen müssen mit mehr "Informationen" als die letztere, aber nach meiner Frage, ich glaube nicht, dass es wirklich funktioniert.

Eine Nutzung: die zurückgegebenen aktuelle Wert kann verwendet werden, für eine Wiederholung. Ich weiß, es sind atomic-Schritten, aber zur illustration Zweck angenommen, Sie implementieren möchten. Rufen Sie einfach die val_compare_and_swap mit oldvalue als Prä-Inkrement-und newvalue wie die pos-Inkrement. Wenn es gelingt, sind Sie fertig. Wenn nicht, Sie können versuchen, durch Erhöhung der zurückgegebene Wert und Aufruf val_compare_and_swap wieder. Mit dem bool-version, die Sie tun müssen, würde eine zusätzliche Lesen des aktuellen Werts für "wiederholen".
Du hast Recht, dass der code in den "neben" buggy ist/hat einen schweren race-Bedingung. Ein retry-Schleife wird benötigt, um es zu korrigieren. Siehe meine Antwort.

InformationsquelleAutor Andrew Parker | 2015-04-28

Schreibe einen Kommentar