- 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;
}
"Атомарная" раздача айдишек.
WGH 28.10.2012 19:38 # +2
P.S. А, пардон, дошло. Между третьей и четвертой строчкой может произойти что угодно.
bormand 28.10.2012 19:48 # +2
Да, все верно, для интереса проводил эксперимент - 5-10% полученных айдишек совпадают. Правильный код был бы:
sayidandrtfm 28.10.2012 19:51 # +3
__sync_add_and_fetch(&id, 1);
pthread_mutex_unlock(&rand_mutex);
return id;
bormand 28.10.2012 20:16 # 0
USB 29.10.2012 00:17 # 0
А может там даже 100 ня.
TarasB 28.10.2012 20:48 # +2
inkanus-gray 28.10.2012 20:51 # +1
> Между третьей и четвертой строчкой может произойти что угодно.
А если так?
bormand 28.10.2012 20:57 # +2
inkanus-gray 28.10.2012 21:01 # +2
bormand 28.10.2012 21:04 # +6
inkanus-gray 28.10.2012 21:05 # 0
bormand 28.10.2012 21:08 # +7
TarasB 28.10.2012 22:41 # 0
3.14159265 28.10.2012 22:58 # +1
Cмысл volatile немного другой - отключение оптимизации.
А вот CAS даст 100% гарантию.
USB 29.10.2012 00:18 # +2
3.14159265 28.10.2012 23:01 # 0
http://msdn.microsoft.com/en-us/library/12a04hfd(VS.80).aspx
volatile будет гарантировать атомность. Вот суки, приучают же людей
ЕМНИП даже для bool нет никаких гарантий. Только лочка или CAS.
bormand 29.10.2012 06:29 # 0
Атомарность чтения и записи - да. В том смысле, что половина переменной не запишется... Тут их выпендреж разве что в барьерах около чтений\записей в volatile переменные.
А вот инкремент всяко превратится в честное [загрузить - увеличить - сохранить].
defecate-plusplus 28.10.2012 23:03 # 0
3.14159265 28.10.2012 23:11 # 0
Это зависит от многих факторов. Может на твоём селероне оно и будет, а на другой машине - нет. Я уверен можно даже написать пример, который будет это демонстрировать:
Вот смотри. long, который в памяти - 64 бита, на 32-битной машине оно как за одно действие?
>старый же никаких многопоточностей не предполагал
Лолшто? А зачем тогда вообще volatile ввели?
TarasB 28.10.2012 23:25 # +1
Компилировать в говно с секциями.
USB 29.10.2012 00:21 # +1
О чем ты?
TarasB 29.10.2012 16:00 # +1
LispGovno 29.10.2012 16:18 # +2
bormand 29.10.2012 06:38 # +1
Ну а __sync_* примерно так и работают. Если платформа позволяет - компилятор пытается описать их одной специальной инструкцией, если не позволяет - через говнище с compare-and-swap.
> Компилировать в говно с секциями.
Ну до такого вроде дело не доходит, емнип обходится циклом с compare-and-swap.
> разве не в атомарный add компилируется
Нет. Обычный инкремент компилится в самый обычный add и не предполагает никакой атомарности. А вот __sync_add_and_fetch превратится в что-то такое:
TarasB 29.10.2012 16:00 # 0
LispGovno 29.10.2012 16:02 # +1
it is not atomic operation
bormand 29.10.2012 16:28 # +1
defecate-plusplus 28.10.2012 23:26 # +1
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
roman-kashitsyn 29.10.2012 00:14 # 0
USB 29.10.2012 00:22 # 0
roman-kashitsyn 29.10.2012 00:23 # +2
> то о чем ты говоришь, появилось только в С++11
Спасибо, ты прям открыл мне глаза
USB 29.10.2012 00:25 # +3
3.14159265 29.10.2012 15:52 # +3
volatile исторически был и будет хинтом компилятору:
avoid aggressive optimization because the value of the object might be changed
Многопоточный код не то место где стоит вводить такого рода "оптимизации" и экономить ставя volatile вместо лочки или cas.
Вот если там где написано atomic - это да.
Я бы лично не рисковал. Пусть там что в новом стандарте. Всегда найдется глючный компилятор или Тарас, который решит скомпилить под старую студию.
Пользователи не будут благодарны за пару сэкономленных тактов. А вот за странные баги они будут ненавидеть и проклинать быдлокодера-оптимизатора.
defecate-plusplus 29.10.2012 16:05 # 0
3.14159265 29.10.2012 16:11 # 0
Но потом переросло в ответ про "новый стандарт". И про то что надо соблюдать обратную совместимость, а не слушать мелкософт.
LispGovno 29.10.2012 16:10 # 0
> глючный Тарас
No way
TarasB 29.10.2012 16:19 # −2
LispGovno 29.10.2012 16:22 # −1
guest 30.10.2012 02:21 # +1
LispGovno 30.10.2012 09:53 # −1
He is a robot? Hardware device Taras haven't bugs, but he have bugs in firmware?
defecate-plusplus 30.10.2012 09:59 # +4
нас заебало
LispGovno 30.10.2012 10:08 # −3
Also it in rules is not forbidden.
defecate-plusplus 30.10.2012 10:14 # +2
inkanus-gray 01.11.2012 01:24 # +3
Fai 01.11.2012 19:41 # +3
без goto пожалуйста.
roman-kashitsyn 30.10.2012 10:16 # +5
Почему ты пишешь по-русски английскими словами?
LispGovno 30.10.2012 10:39 # −2
USB 29.10.2012 00:20 # 0
> Лолшто? А зачем тогда вообще volatile ввели?
Например для работы в условиях сигналов или прерываний
3.14159265 29.10.2012 15:51 # 0
Если смотреть вглубь, то треды в ОС и реализованы как сигналы и прерывания.
bormand 29.10.2012 06:31 # +1
А он возьмет соптимизирует это, и выкинет нахер Port = 1, если переменная не volatile. Так что оно и без тредов полезно.
bormand 29.10.2012 06:24 # +1
Для волатильного - нет. Он компилируется как и положено в [загрузить - увеличить - записать]. Поэтому баги с инкрементом тут гарантированы.
bormand 29.10.2012 07:26 # 0
Да и в большинстве случаев атомарность не нужна, например если некая структура защищена мутексом, и мы не забываем его получать и отпускать, то в ней атомарный i++ будет совершенно бесполезным оверхедом.