std :: atomic |сравнить_экспорт_слабый - PullRequest
28 голосов
/ 09 февраля 2011

Я не уверен, что это я не понимаю или документация четко не сформулирована.

Следующая выдержка была взята из новейшего черновика (N3126, раздел 29.6):

bool atomic_compare_exchange_weak(volatile A* object, C * expected, C desired);
bool atomic_compare_exchange_weak(A* object, C * expected, C desired);
bool atomic_compare_exchange_strong(volatile A* object, C * expected, C desired);
bool atomic_compare_exchange_strong(A* object, C * expected, C desired);
bool atomic_compare_exchange_weak_explicit(volatile A* object, C * expected, C desired, memory_order success, memory_order failure);
bool atomic_compare_exchange_weak_explicit(A* object, C * expected, C desired, memory_order success, memory_order failure);
bool atomic_compare_exchange_strong_explicit(volatile A* object, C * expected, C desired, memory_order success, memory_order failure);
bool atomic_compare_exchange_strong_explicit(A* object, C * expected, C desired, memory_order success, memory_order failure);
bool A::compare_exchange_weak(C & expected, C desired, memory_order success, memory_order failure) volatile;
bool A::compare_exchange_weak(C & expected, C desired, memory_order success, memory_order failure);
bool A::compare_exchange_strong(C & expected, C desired, memory_order success, memory_order failure) volatile;
bool A::compare_exchange_strong(C & expected, C desired, memory_order success, memory_order failure);
bool A::compare_exchange_weak(C & expected, C desired, memory_order order = memory_order_seq_cst) volatile;
bool A::compare_exchange_weak(C & expected, C desired, memory_order order = memory_order_seq_cst);
bool A::compare_exchange_strong(C & expected, C desired, memory_order order = memory_order_seq_cst) volatile;
bool A::compare_exchange_strong(C & expected, C desired, memory_order order = memory_order_seq_cst);

Примечание. Слабые операции сравнения и обмена могут внезапно завершаться неудачей, то есть возвращать false, оставляя содержимое памяти, на которое указывает ожидаемое, до того, как операция станет такой же, как и у объекта и объекта.такой же, как ожидалось после операции.[Примечание: этот ложный сбой позволяет реализовать сравнение и обмен на более широком классе машин, например, на машинах с условной загрузкой и блокировкой.Следствием ложного сбоя является то, что почти все виды использования слабого сравнения и обмена будут в цикле.

Итак, что это значит?

Во-первых, это может'сбои с энтузиазмом ?!Почему бы это не удалось?И как они определяют «может»?

Во-вторых, я до сих пор не знаю, в чем разница между функциями с суффиксами «_strong» и «_weak».Может ли кто-нибудь объяснить разницу?

РЕДАКТИРОВАТЬ: Вот что я нашел в libstdc ++ - реализация (atomic_0.h):

bool compare_exchange_weak(
    __integral_type& __i1,
    __integral_type __i2,
    memory_order __m1,
    memory_order __m2
)
{
    __glibcxx_assert(__m2 != memory_order_release);
    __glibcxx_assert(__m2 != memory_order_acq_rel);
    __glibcxx_assert(__m2 <= __m1);
    return _ATOMIC_CMPEXCHNG_(this, &__i1, __i2, __m1);
}

bool compare_exchange_strong(
    __integral_type& __i1,
    __integral_type __i2,
    memory_order __m1,
    memory_order __m2
)
{
    __glibcxx_assert(__m2 != memory_order_release);
    __glibcxx_assert(__m2 != memory_order_acq_rel);
    __glibcxx_assert(__m2 <= __m1);
    return _ATOMIC_CMPEXCHNG_(this, &__i1, __i2, __m1);
}

Ответы [ 2 ]

30 голосов
/ 12 марта 2013

В примечании содержится подсказка, относящаяся к LL / SC архитектурам. Из статьи в Википедии:

Если произошли какие-либо обновления, условное хранилище гарантированно не будет выполнено, даже если с тех пор значение, прочитанное загрузочной ссылкой, было восстановлено. Таким образом, пара LL / SC сильнее, чем чтение, за которым следует сравнение и замена (CAS), которое не будет обнаруживать обновления, если старое значение было восстановлено (см. Проблему ABA).

Реальные реализации LL / SC не всегда успешны, если нет одновременных обновлений в рассматриваемой области памяти. Любые исключительные события между этими двумя операциями, такие как переключение контекста, другая ссылка для загрузки или даже (на многих платформах) другая операция загрузки или сохранения, приводят к случайному отказу условного хранилища.

На микросхемах LL / SC compare_exchange будет реализован в терминах LL / SC, который может внезапно завершиться сбоем, поэтому compare_exchange_strong требуется дополнительная служебная информация для повторной попытки в случае сбоя. Предоставление как compare_exchange_strong, так и compare_exchange_weak позволяет программисту решать, хотят ли они, чтобы библиотека обрабатывала ложные сбои (в этом случае они использовали бы compare_exchange_strong или они хотели бы обрабатывать это в своем собственном коде (в этом случае они использовал бы compare_exchange_weak)

11 голосов
/ 09 февраля 2011

Это связано с моделью согласованности совместно используемой памяти, которую реализует аппаратное обеспечение. Для тех аппаратных архитектур, которые реализуют какую-то модель смягченной согласованности (например, семантику релиза), сильные операции, на которые вы ссылаетесь выше, могут иметь большие накладные расходы, и, таким образом, эксперты могут использовать более слабые формы для реализации алгоритмов, которые хорошо работают и на этой расслабленной согласованности архитектуры.

Для получения дополнительной информации см., Например,

http://www.hpl.hp.com/techreports/Compaq-DEC/WRL-95-7.pdf

Глава 12 и Приложение C в http://kernel.org/pub/linux/kernel/people/paulmck/perfbook/perfbook.html

...