Size: a a a

2020 June 22

S

Serg in pro.cxx
что такое "happens before"?
источник

S

Serg in pro.cxx
Кольцевой буфер не требует mutex, можно spin-lock обойтись
источник

m

magras in pro.cxx
Serg
что такое "happens before"?
Это термин из описания модли памяти в стандарте C++.
источник

OS

Oleksandr Senkovych in pro.cxx
хорошее видео, спасибо
источник

S

Serg in pro.cxx
ну я согласен что нужны гарантии модели памяти. Но они не эквивалентны гарантиям atomic-перменной
источник

S

Serg in pro.cxx
эти гарантии дает x86 модель либо, барьеры вставляетмяе MSVC для volatile Для не-x86
источник

AS

Anatoly Shirokov in pro.cxx
Oleksandr Senkovych
хорошее видео, спасибо
#барьеры_памяти лекция была построена на этом материале https://habr.com/ru/post/196548/
источник

m

magras in pro.cxx
Serg
ну я согласен что нужны гарантии модели памяти. Но они не эквивалентны гарантиям atomic-перменной
В стандарте C++ atomic'и вводятся как раз через модель памяти и описываться в этих терминах.
источник

S

Serg in pro.cxx
magras
В стандарте C++ atomic'и вводятся как раз через модель памяти и описываться в этих терминах.
верно, на основе знания модели памяти можно построить atomic переменные, когда они нужны
но они нужны не всегда, когда полезны модели памяти
источник

OS

Oleksandr Senkovych in pro.cxx
Serg
верно, на основе знания модели памяти можно построить atomic переменные, когда они нужны
но они нужны не всегда, когда полезны модели памяти
на одной модели не построишь. модель памяти не говорит например  что на i386 запись в int64 происходит не атомарно
источник

S

Serg in pro.cxx
Oleksandr Senkovych
на одной модели не построишь. модель памяти не говорит например  что на i386 запись в int64 происходит не атомарно
это да - особый случай, как и запись/чтение по не ровному адресу
источник

S

Serg in pro.cxx
но некоторые алгоритмы можно построить без atomic
источник

m

magras in pro.cxx
Serg
Кольцевой буфер не требует mutex, можно spin-lock обойтись
Можете показать как вы будете, доавлять или удалять элемент из буфера? По-моему вам в любом случае понадобится атомарный swap указателей или индекса. Как вы это будете писать с volatile от ms?
источник

S

Serg in pro.cxx
magras
Можете показать как вы будете, доавлять или удалять элемент из буфера? По-моему вам в любом случае понадобится атомарный swap указателей или индекса. Как вы это будете писать с volatile от ms?
для простоты не кольцевой а бесконечный линенй буфер:


char buf[1000000000];
char * volatile begin = buf, * volatile end = buf;
void Write(char ch) {
 *end = ch;
 ++end;
}

char Read() {
 while (begin == end)
     sleep(1);
 char r = *begin;
 ++begin;
 return r;
}
источник

S

Serg in pro.cxx
Read() и Write() могут вызываться из 2-х разных потоков
источник

m

magras in pro.cxx
Serg
для простоты не кольцевой а бесконечный линенй буфер:


char buf[1000000000];
char * volatile begin = buf, * volatile end = buf;
void Write(char ch) {
 *end = ch;
 ++end;
}

char Read() {
 while (begin == end)
     sleep(1);
 char r = *begin;
 ++begin;
 return r;
}
Кажется, с точки зрения сгенерированного asm'а результат и в правду корректный, пока reader и writer существуют в единственном экземпляре. Если считать, что чтение/запись volatile атомарны, код вроде корректен и с точки зрения стандарта.

Вроде для меня пазл сложился, хотя как всегда с атомиками у меня нет в этом уверенности.

Спасибо за поучительную беседу.
источник

S

Serg in pro.cxx
спасибо Вам
источник

S

Serg in pro.cxx
для гарантии атомарности  чтения/записи можно использовать atomic_store()/ atomic_load() - ассемблерный код будет тот же
источник

m

magras in pro.cxx
Serg
для простоты не кольцевой а бесконечный линенй буфер:


char buf[1000000000];
char * volatile begin = buf, * volatile end = buf;
void Write(char ch) {
 *end = ch;
 ++end;
}

char Read() {
 while (begin == end)
     sleep(1);
 char r = *begin;
 ++begin;
 return r;
}
Кстати, на атомиках можно написать эквивалентный код: https://godbolt.org/z/JiD9Ar

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

Если я правильно понимаю, операция ++ms_specific_volatile на атомики транслируется как-то так:
auto t = volatile.load(std::memory_order::memory_order_acquire);
++t;
volatile.store(t, std::memory_order::memory_order_release);
return t;

В общем хорошо, что у нас теперь есть нормальные атомики.
источник

AS

Anatoly Shirokov in pro.cxx
Serg
для простоты не кольцевой а бесконечный линенй буфер:


char buf[1000000000];
char * volatile begin = buf, * volatile end = buf;
void Write(char ch) {
 *end = ch;
 ++end;
}

char Read() {
 while (begin == end)
     sleep(1);
 char r = *begin;
 ++begin;
 return r;
}
источник