- 01
- 02
- 03
- 04
- 05
- 06
- 07
- 08
- 09
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
#include <stdint.h>
#include <Windows.h>
#include <intrin.h>
typedef long dt;
namespace {
dt InitializationIsInProgress = 0;
dt InitializationIsFinished = 0;
}
dt InterlockedLoad(dt volatile * t){
return InterlockedCompareExchange(t, 0, 0);
}
dt InterlockedAssign(dt volatile * t, dt v){
dt c = 0;
while (c = InterlockedCompareExchange(t, v, c));
}
void InitializeSystem(){
if (InterlockedLoad(&InitializationIsFinished) == 1)
return;
while (InterlockedCompareExchange(&InitializationIsInProgress, 1, 0) == 1) Sleep(0);
//__ReadWriteBarrier();
if (InterlockedLoad(&InitializationIsFinished) == 1)
return;
Work();
InterlockedAssign(&InitializationIsFinished, 1);
InterlockedAssign(&InitializationIsInProgress, 0);
}
Не судите строга. Воспользуюсь как пастебином. Если найдете ошибки - пришлю пирожок.
Помещаем в переменную 0 если в ней был ноль? Вот зе фак?
Цикл можно убрать, емнип, только поставив какой-нить wait condition (event в winapi) но там начинается проблема с тем, кто будет его запиливать...
Я только про данный случай.
atomic_store() аля InterlockedAssign(), емнип, просто запись в правильно выровненную переменную + фенс нужного типа (если relaxed - то просто запись безо всяких фенсов)...
Т.е. под msvc можно сделать переменную со статусом volatile и правильно выровнять её. Тогда самая обычная запись в неё будет atomic_store с release семантикой. А самое обычное чтение - atomic_load с aquire семантикой. Должно работать даже на ARM'ах с вендой.
а есть и классический Thread.MemoryBarrier().
из разряда - "очень занимательно но нахуй не нужно"
На кешлайн равняют чтобы поднять производительность для независимых переменных.