C ++ 0x | Почему std :: atomic перегружает каждый метод квалификатором volatile? - PullRequest
7 голосов
/ 02 февраля 2011

Следующая выдержка из текущего проекта показывает, что я имею в виду:

namespace std {
    typedef struct atomic_bool {
        bool is_lock_free() const volatile;
        bool is_lock_free() const;
        void store(bool, memory_order = memory_order_seq_cst) volatile;
        void store(bool, memory_order = memory_order_seq_cst);
        bool load(memory_order = memory_order_seq_cst) const volatile;
        bool load(memory_order = memory_order_seq_cst) const;
        operator bool() const volatile;
        operator bool() const;
        bool exchange(bool, memory_order = memory_order_seq_cst) volatile;
        bool exchange(bool, memory_order = memory_order_seq_cst);
        bool compare_exchange_weak(bool&, bool, memory_order, memory_order) volatile;
        bool compare_exchange_weak(bool&, bool, memory_order, memory_order);
        bool compare_exchange_strong(bool&, bool, memory_order, memory_order) volatile;
        bool compare_exchange_strong(bool&, bool, memory_order, memory_order);
        bool compare_exchange_weak(bool&, bool, memory_order = memory_order_seq_cst) volatile;
        bool compare_exchange_weak(bool&, bool, memory_order = memory_order_seq_cst);
        bool compare_exchange_strong(bool&, bool, memory_order = memory_order_seq_cst) volatile;
        bool compare_exchange_strong(bool&, bool, memory_order = memory_order_seq_cst);
        atomic_bool() = default;
        constexpr atomic_bool(bool);
        atomic_bool(const atomic_bool&) = delete;
        atomic_bool& operator=(const atomic_bool&) = delete;
        atomic_bool& operator=(const atomic_bool&) volatile = delete;
        bool operator=(bool) volatile;
    } atomic_bool;
}

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

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

Ответы [ 2 ]

4 голосов
/ 02 февраля 2011

Я думаю, что энергозависимые перегрузки существуют по соображениям эффективности. Волатильное чтение и запись по своей природе дороже, чем энергонезависимое чтение и запись в C ++ 0x, поскольку модель памяти предъявляет некоторые строгие требования, которые предотвращают кэширование значений изменчивых переменных. Если бы все функции были помечены только как volatile, тогда код не мог бы выполнять определенные оптимизации, которые иначе повысили бы производительность. Наличие различия позволяет компилятору оптимизировать энергонезависимые операции чтения и записи, когда это возможно, при постепенном снижении, когда требуются энергозависимые операции чтения и записи.

0 голосов
/ 03 февраля 2011

Во-первых, это звучит избыточно, чтобы создать изменчивый std :: atomic. На самом деле, я могу представить себе полезную ситуацию. Предполагая, что у нас есть фиксированный адрес устройства (памяти), с которым мы хотим работать. Ввиду того, что классы std :: atomic_xxx, а также размеры классов шаблонов std :: atomic <> должны иметь одинаковый размер с соответствующими им встроенными типами, вы можете обрабатывать оба: упорядочение памяти и убедитесь, что доступ к нашему атомарному объекту никогда не оптимизируется. Таким образом, мы можем объявить что-то вроде:

std::atomic<long> volatile* vmem_first4 = reinterpret_cast<std::atomic<long> volatile*>(0xxB8000);
...