|
849 | 849 | \tcode{memory_order::acq_rel}.
|
850 | 850 |
|
851 | 851 | \pnum
|
852 |
| -\effects Retrieves the value in \tcode{expected}. It then atomically |
853 |
| -compares the contents of the memory pointed to by \tcode{this} |
| 852 | +\effects |
| 853 | +Retrieves the value in \tcode{expected}. It then atomically |
| 854 | +compares the value representation of the value pointed to by \tcode{this} |
854 | 855 | for equality with that previously retrieved from \tcode{expected},
|
855 |
| -and if true, replaces the contents of the memory pointed to |
| 856 | +and if true, replaces the value pointed to |
856 | 857 | by \tcode{this} with that in \tcode{desired}.
|
857 | 858 | If and only if the comparison is true, memory is affected according to the
|
858 | 859 | value of \tcode{success}, and if the comparison is false, memory is affected according
|
|
863 | 864 | \tcode{memory_order::release} shall be replaced by the value
|
864 | 865 | \tcode{memory_order::relaxed}.
|
865 | 866 | If and only if the comparison is false then, after the atomic operation,
|
866 |
| -the contents of the memory in \tcode{expected} are replaced by the value |
867 |
| -read from the memory pointed to by \tcode{this} during the atomic comparison. |
| 867 | +the value in \tcode{expected} is replaced by the value |
| 868 | +pointed to by \tcode{this} during the atomic comparison. |
868 | 869 | If the operation returns \tcode{true}, these
|
869 | 870 | operations are atomic read-modify-write
|
870 | 871 | operations\iref{intro.multithread} on the memory
|
|
875 | 876 | \returns The result of the comparison.
|
876 | 877 |
|
877 | 878 | \pnum
|
878 |
| -\begin{note} For example, the effect of |
879 |
| -\tcode{compare_exchange_strong} is |
| 879 | +\begin{note} |
| 880 | +For example, the effect of |
| 881 | +\tcode{compare_exchange_strong} |
| 882 | +on objects without padding bits\iref{basic.types} is |
880 | 883 | \begin{codeblock}
|
881 | 884 | if (memcmp(this, &expected, sizeof(*this)) == 0)
|
882 | 885 | memcpy(this, &desired, sizeof(*this));
|
|
928 | 931 | \end{note}
|
929 | 932 |
|
930 | 933 | \pnum
|
931 |
| -\begin{note} The \tcode{memcpy} and \tcode{memcmp} semantics of the compare-and-exchange |
932 |
| -operations may result in failed comparisons for values that compare equal with |
933 |
| -\tcode{operator==} if the underlying type has padding bits, trap bits, or alternate |
| 934 | +\begin{note} |
| 935 | +Under cases where the \tcode{memcpy} and \tcode{memcmp} semantics of the compare-and-exchange |
| 936 | +operations apply, the outcome might be failed comparisons for values that compare equal with |
| 937 | +\tcode{operator==} if the underlying type has trap bits or alternate |
934 | 938 | representations of the same value. Notably, on implementations conforming to
|
935 | 939 | ISO/IEC/IEEE 60559, floating-point \tcode{-0.0} and \tcode{+0.0}
|
936 | 940 | will not compare equal with \tcode{memcmp} but will compare equal with \tcode{operator==},
|
937 | 941 | and NaNs with the same payload will compare equal with \tcode{memcmp} but will not
|
938 |
| -compare equal with \tcode{operator==}.\end{note} |
| 942 | +compare equal with \tcode{operator==}. |
| 943 | +\end{note} |
| 944 | +\begin{note} |
| 945 | +Because compare-and-exchange acts on an object's value representation, |
| 946 | +padding bits that never participate in the object's value representation |
| 947 | +are ignored. As a consequence, the following code is guaranteed to avoid |
| 948 | +spurious failure: |
| 949 | +\begin{codeblock} |
| 950 | +struct padded { |
| 951 | + char clank = 0x42; |
| 952 | + // Padding here. |
| 953 | + unsigned biff = 0xC0DEFEFE; |
| 954 | +}; |
| 955 | +atomic<padded> pad = ATOMIC_VAR_INIT({}); |
| 956 | + |
| 957 | +bool zap() { |
| 958 | + padded expected, desired{0, 0}; |
| 959 | + return pad.compare_exchange_strong(expected, desired); |
| 960 | +} |
| 961 | +\end{codeblock} |
| 962 | +\end{note} |
| 963 | +\begin{note} |
| 964 | +For a union with bits that participate in the value representation |
| 965 | +of some members but not others, compare-and-exchange might always fail. |
| 966 | +This is because such padding bits have an indeteminate value when they |
| 967 | +do not participate in the value representation of the active member. |
| 968 | +As a consequence, the following code is not guaranteed to ever succeed: |
| 969 | +\begin{codeblock} |
| 970 | +union pony { |
| 971 | + double celestia = 0.; |
| 972 | + short luna; // padded |
| 973 | +}; |
| 974 | +atomic<pony> princesses = ATOMIC_VAR_INIT({}); |
| 975 | + |
| 976 | +bool party(pony desired) { |
| 977 | + pony expected; |
| 978 | + return princesses.compare_exchange_strong(expected, desired); |
| 979 | +} |
| 980 | +\end{codeblock} |
| 981 | +\end{note} |
939 | 982 | \end{itemdescr}
|
940 | 983 |
|
941 | 984 | \rSec2[atomics.types.int]{Specializations for integers}
|
|
0 commit comments