Атомарный доступ к переменной, которая не является `std :: atomic` - PullRequest
0 голосов
/ 05 июня 2018

У нас есть старый код, который мы обновляем, чтобы использовать более современный c ++.Ранее он использовал (yucky) расширение визуальной студии для volatile для атомарного доступа к переменной.

Эта функция похожа на

T ReadAq(T* val)
{
    return *(volatile T*)val;
}

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

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

И я действительно не хочу менять свою подпись (так как это было бы огромным изменением для всех вызывающих абонентов), поэтому я хочу иметь возможность сделать что-то вроде:

T ReadAq(T* val)
{
    return std::atomic_read(val, std::memory_order_acquire);
}

Но это похоже на функциональностькак это не существует в стандарте - все атомарные операции выполняются на типах std :: atomic.Любые идеи о том, можно ли это исправить без изменения подписи ReadAq?

Ответы [ 2 ]

0 голосов
/ 13 июля 2018

Кажется, что это действительно пробел в языке, и есть предложение исправить это для c ++ 20:

p0019R7: Atomic Ref

Аннотация: Расширение библиотеки атомарных операций, позволяющее применять атомарные операции к неатомарным объектам

Атомная ссылка используется для выполнения атомарных операций над ссылочным неатомарным объектом.Цель состоит в том, чтобы обеспечить атомарную ссылку, чтобы обеспечить наиболее эффективную реализацию атомарных операций для неатомарного типа объекта.Все атомарные операции, выполняемые с помощью атомарной ссылки на неатомный объект, на который есть ссылка, являются атомарными по отношению к любой другой атомарной ссылке, которая ссылается на тот же объект, как определено равенством указателей на этот объект.Целью является атомарные операции для непосредственного обновления ссылочного объекта.Конструктор атомарных ссылок может получить ресурс, такой как блокировка из коллекции блокированных адресом блокировок, для выполнения атомарных операций.Такие атомарные ссылочные объекты не свободны от блокировки и не свободны от адресаКогда такой ресурс необходим, последующие конструкторы копирования и перемещения и операторы присваивания могут уменьшить накладные расходы, копируя или перемещая ранее полученный ресурс, в отличие от повторного получения этого ресурса.

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

Объект может интенсивно использоваться неатомно в четко определенных фазах приложения.Принудительное использование таких объектов в качестве атомарных компонентов приведет к излишнему снижению производительности.

0 голосов
/ 05 июня 2018

Вы можете сделать это с осторожным броском:

template<class T>
T ReadAq(T* val) {
    using AT = std::atomic<T>;
    static_assert(sizeof(T) == sizeof(AT), "Incompatible layout.");
    static_assert(alignof(T) == alignof(AT), "Incompatible layout.");
    return reinterpret_cast<AT*>(val)->load(std::memory_order_acquire);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...