Какие-нибудь недостатки для std :: atomic_flag, не обеспечивающего операции загрузки или хранения? (Пример Spin-Lock) - PullRequest
0 голосов
/ 29 августа 2018

Сравнивая std::atomic_flag с std::atomic_bool (он же std::atomic<bool>), мне кажется, что std::atomic_flag просто имеет более простой интерфейс. Он обеспечивает только проверку + установку и очистку флага, в то время как std::atomic_bool также обеспечивает перегрузки для нескольких операторов.

Один мой вопрос касается терминологии: что подразумевается под «операциями загрузки или хранения»? Означает ли это, что невозможно произвольно прочитать и изменить значение std::atomic_flag?

Кроме того, мне интересно, может ли std::atomic_bool быть быстрее при использовании для спин-блокировки? Мне кажется, что std::atomic_flag всегда должен читать и писать во время спин-блокировки:

while (my_atomic_flag.test_and_set()); // spin-lock

, в то время как std::atomic_bool должен был бы только выполнить операцию чтения (при условии, что атомарный тип bool реализован без блокировки):

while (my_atomic_bool); // spin-lock

Является ли std::atomic_flag строго более эффективным, чем std::atomic_bool, или он может быть и наоборот? Что следует использовать для спин-блокировки?

1 Ответ

0 голосов
/ 29 августа 2018

Что подразумевается под «операциями загрузки или хранения»? Означает ли это, что невозможно произвольно прочитать и изменить значение std :: atomic_flag?

Обычные операции сохранения / загрузки не поддерживаются на std::atomic_flag.
Это тип только для модификации; то есть. Вы не можете получить доступ к объекту std::atomic_flag для чтения без выполнения операции изменения.
В общем, std::atomic_flag подразумевается как строительный блок для других операций. Его интерфейс преднамеренно прост; это единственный атомарный тип, который имеет гарантированные атомарные операции без блокировки. Поддерживаемые операции:

std::atomic_flag::clear()
std::atomic_flag::test_and_set()

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

class my_spinlock {
    std::atomic_flag flag = ATOMIC_FLAG_INIT;
public:

    void lock()
    {
        while(flag.test_and_set());
    }

    void unlock()
    {
        flag.clear();
    }
};

Кроме того, мне интересно, может ли std :: atomic_bool быть быстрее при использовании для спин-блокировки? Мне кажется, что std :: atomic_flag всегда должен читать и писать во время спин-блокировки

Ну, дело в том, что спин-блокировка всегда должна изменять свое состояние при получении блокировки. Вы просто не можете взломать замок, не сказав другим.
Реализация для lock() на основе std::atomic<bool> выглядит очень похоже:

while (flag.exchange(true)); 

Быстрее ли спинлок на основе std::atomic_flag?
На моей платформе компилятор выдает одинаковую сборку для обоих типов, поэтому я был бы очень удивлен.

...