Почему ожидаемый параметр для std :: atomic :: compare_exchange_xxx () не является константой &? - PullRequest
0 голосов
/ 14 октября 2018

Я уверен, что у меня будет момент с лицом-ладонью, но здесь идет речь:

Прототип для std::atomic::compare_expected_* это

bool compare_exchange_strong (T& expected, T val,
       memory_order sync = memory_order_seq_cst) volatile noexcept;

Почему expectedне const T &?

static const handle_t INVALID_HANDLE = 0;
...
std::atomic<handle_t> handle(INVALID_HANDLE);
...
handle.compare_exchange_strong(INVALID_HANDLE, newValue);

Конечно, методы обмена не должны изменять ожидаемое значение?

Ответы [ 3 ]

0 голосов
/ 14 октября 2018

cppreference.com :

Атомно сравнивает объектное представление *this с представлением expected и, если оно поразрядно равно, заменяет первое натребуемый (выполняет операцию чтения-изменения-записи).В противном случае загружает фактическое значение, сохраненное в *this, в expected (выполняет операцию загрузки).

0 голосов
/ 14 октября 2018

TL; DR: поскольку, если ожидаемый параметр был ссылкой const, compare_exchange не сможет изменить его при сбое обмена.


Вы предоставляете оба параметра ожидаемое и желаемое значение до compare_exchange.Он изменяет ваше ожидаемое значение, если он находит значение, отличное от того, которое вы указали.В этом случае ожидаемое значение не заменяется указанным вами желаемым значением (т. Е. Оно не удалось обменять, поэтому вы можете попытаться обменять значение снова).

Обычно вы хотите использоватьэти функции в цикле, по этой причине изменение ожидаемого значения, которое вы указали, имеет смысл, поскольку предоставляет вам обновленную версию ожидаемого значения.

Рассмотрим следующее атомное значение:

std::atomic<int> a = 7;

, и вы хотите удвоить значение a:

int expected = a.load(), desired;
do {
  desired = 2 * expected;
} while (!a.compare_exchange_weak(expected, desired));

В приведенном выше коде, если aперед обменом изменяется другим потоком, expected обновляется на compare_exchange значением a в момент попытки обмена (т. е. в момент сбоя).

В противном случае, если expected не был изменен на compare_exchange в случае сбоя, вам нужно будет загрузить значение a на каждой итерации цикла, чтобы обновить expected:

int expected, desired;
do {
  expected = a.load(); // <-- load on each iteration
  desired = 2 * expected;
} while (!a.compare_exchange_weak(expected, desired));
0 голосов
/ 14 октября 2018

Изменяет expected при сбое.

...