- 1
- 2
- 3
- 4
- 5
int next_id() {
static int id = 0;
__sync_add_and_fetch(&id, 1);
return id;
}
Нашли или выдавили из себя код, который нельзя назвать нормальным, на который без улыбки не взглянешь? Не торопитесь его удалять или рефакторить, — запостите его на говнокод.ру, посмеёмся вместе!
+140
int next_id() {
static int id = 0;
__sync_add_and_fetch(&id, 1);
return id;
}
"Атомарная" раздача айдишек.
P.S. А, пардон, дошло. Между третьей и четвертой строчкой может произойти что угодно.
Да, все верно, для интереса проводил эксперимент - 5-10% полученных айдишек совпадают. Правильный код был бы:
__sync_add_and_fetch(&id, 1);
pthread_mutex_unlock(&rand_mutex);
return id;
А может там даже 100 ня.
> Между третьей и четвертой строчкой может произойти что угодно.
А если так?
Cмысл volatile немного другой - отключение оптимизации.
А вот CAS даст 100% гарантию.
http://msdn.microsoft.com/en-us/library/12a04hfd(VS.80).aspx
volatile будет гарантировать атомность. Вот суки, приучают же людей
ЕМНИП даже для bool нет никаких гарантий. Только лочка или CAS.
Атомарность чтения и записи - да. В том смысле, что половина переменной не запишется... Тут их выпендреж разве что в барьерах около чтений\записей в volatile переменные.
А вот инкремент всяко превратится в честное [загрузить - увеличить - сохранить].
Это зависит от многих факторов. Может на твоём селероне оно и будет, а на другой машине - нет. Я уверен можно даже написать пример, который будет это демонстрировать:
Вот смотри. long, который в памяти - 64 бита, на 32-битной машине оно как за одно действие?
>старый же никаких многопоточностей не предполагал
Лолшто? А зачем тогда вообще volatile ввели?
Компилировать в говно с секциями.
О чем ты?
Ну а __sync_* примерно так и работают. Если платформа позволяет - компилятор пытается описать их одной специальной инструкцией, если не позволяет - через говнище с compare-and-swap.
> Компилировать в говно с секциями.
Ну до такого вроде дело не доходит, емнип обходится циклом с compare-and-swap.
> разве не в атомарный add компилируется
Нет. Обычный инкремент компилится в самый обычный add и не предполагает никакой атомарности. А вот __sync_add_and_fetch превратится в что-то такое:
it is not atomic operation
c++03
7.1.5.1 The cv-qualifiers /8
[Note: volatile is a hint to the implementation to avoid aggressive optimization involving the object because the value of the object might be changed by means undetectable by an implementation. See 1.9 for detailed semantics. In general, the semantics of volatile are intended to be the same in C++ as they are in C. ]
ну а слово thread во всем документе упоминается лишь однажды - когда описывается в каком из catch будет выловлено исключение - в ближайшем the try keyword was most recently entered by the thread of control and not yet exited.
вот какбэ и вся многопоточность в с++03
> то о чем ты говоришь, появилось только в С++11
Спасибо, ты прям открыл мне глаза
volatile исторически был и будет хинтом компилятору:
avoid aggressive optimization because the value of the object might be changed
Многопоточный код не то место где стоит вводить такого рода "оптимизации" и экономить ставя volatile вместо лочки или cas.
Вот если там где написано atomic - это да.
Я бы лично не рисковал. Пусть там что в новом стандарте. Всегда найдется глючный компилятор или Тарас, который решит скомпилить под старую студию.
Пользователи не будут благодарны за пару сэкономленных тактов. А вот за странные баги они будут ненавидеть и проклинать быдлокодера-оптимизатора.
Но потом переросло в ответ про "новый стандарт". И про то что надо соблюдать обратную совместимость, а не слушать мелкософт.
> глючный Тарас
No way
He is a robot? Hardware device Taras haven't bugs, but he have bugs in firmware?
нас заебало
Also it in rules is not forbidden.
без goto пожалуйста.
Почему ты пишешь по-русски английскими словами?
> Лолшто? А зачем тогда вообще volatile ввели?
Например для работы в условиях сигналов или прерываний
Если смотреть вглубь, то треды в ОС и реализованы как сигналы и прерывания.
А он возьмет соптимизирует это, и выкинет нахер Port = 1, если переменная не volatile. Так что оно и без тредов полезно.
Для волатильного - нет. Он компилируется как и положено в [загрузить - увеличить - записать]. Поэтому баги с инкрементом тут гарантированы.
Да и в большинстве случаев атомарность не нужна, например если некая структура защищена мутексом, и мы не забываем его получать и отпускать, то в ней атомарный i++ будет совершенно бесполезным оверхедом.