Какова правильная и оптимальная реализация атомного_ref и атомного с битами заполнения?C++

Программы на C++. Форум разработчиков
Ответить Пред. темаСлед. тема
Anonymous
 Какова правильная и оптимальная реализация атомного_ref и атомного с битами заполнения?

Сообщение Anonymous »

TL;DR: Должен ли std::atomic CAS с битами заполнения нулями битов заполнения в конструкторе или обрабатывать их через повторные попытки CAS/маскированный LL/SC? Рассмотрим также Atomic_ref CAS и атомарное ожидание как дляatomic, так и дляatomic_ref.

Некоторые тривиальные типы в C++ не имеют unique_representation, для них std::has_unique_object_representations_v является ложным, это означает, что эквивалентные значения могут не быть равными по битам memcmp.
Один Одной из причин этого является наличие битов заполнения. Биты заполнения — это неиспользуемые биты битового поля, байты выравнивания структуры или дополнительное заполнение, скажем, для 10-байтового числа с плавающей запятой.
C++2a исключил заполнениеatomic::compare_exchange_strong Сравнение и Compare_exchange_weak. См.:
  • Основное предложение P0528R3
    Загадочный случай заполнения битов с использованием атомарного сравнения и обмена
    < li>Ссылка изatomic_ref 5. Проблемы с атомарными битами и битами заполнения в T
Теперь вопрос , как это можно правильно и эффективно реализовать, особенно учитывая наличиеatomic_ref. x86 поддерживает только побитовое равенство в CAS, я ожидаю, что это похоже на другие архитектуры ЦП.
  • Один из способов сделать это — очистить биты заполнения из исходного значения в конструктор, сохраните, обменяйте и очистите нужное значение в Compare_exchange_*. Таким образом, кажется, что конструкторatomic_ref должен быть атомарным, и существует «плата за то, что вы не используете», если операция Compare_exchange не используется.
  • Другой способ Я вижу, что нужно скопировать биты заполнения из наблюдаемого значения в цикле Compare_exchange. Таким образом, цикл CAS завершается только при несовпадении битов значений. Кажется, что это противоречит цели разделения на сильную и слабую CAS, поскольку слабая CAS не должна постоянно давать сбои, а при таком подходе это может произойти. Хотя CAS на основе LL/SC, похоже, способен выполнять внутреннее сравнение с естественным исключением бита заполнения, поэтому возможен слабый CAS без цикла.
Итак, вопросы здесь такие:
  • Какой из подходов (если есть) правильный? Существуют ли другие правильные подходы?
  • Если несколько подходов верны, какой из них обычно более эффективен?
Обратите внимание, что atomic::wait /atomic_ref::wait также приходится иметь дело с битами заполнения, и этот подход должен быть общим.

Обратите внимание, что существует простой способ получить ненулевые биты заполнения:
struct S {
int i : 17;
};
S* s = (S*)malloc(sizeof(S));
s->i = 1;

struct S2 {
std::uint8_t j;
std::uint16_t k;
};

S2* s2 = (S2*)malloc(sizeof(S2));
s2->j = 2;
...
s2->k = 3;



Подробнее здесь: https://stackoverflow.com/questions/629 ... c-with-pad
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «C++»