mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-05-27 22:03:43 -06:00
139 lines
No EOL
6.5 KiB
C++
139 lines
No EOL
6.5 KiB
C++
topic "Thread synchronization primitives";
|
|
[2 $$0,0#00000000000000000000000000000000:Default]
|
|
[i448;a25;kKO9;2 $$1,0#37138531426314131252341829483380:class]
|
|
[l288;2 $$2,0#27521748481378242620020725143825:desc]
|
|
[0 $$3,0#96390100711032703541132217272105:end]
|
|
[H6;0 $$4,0#05600065144404261032431302351956:begin]
|
|
[i448;a25;kKO9;2 $$5,0#37138531426314131252341829483370:item]
|
|
[l288;a4;*@5;1 $$6,6#70004532496200323422659154056402:requirement]
|
|
[l288;i1121;b17;O9;~~~.1408;2 $$7,0#10431211400427159095818037425705:param]
|
|
[i448;b42;O9;2 $$8,8#61672508125594000341940100500538:tparam]
|
|
[b42;2 $$9,9#13035079074754324216151401829390:normal]
|
|
[*C1 $$10,10#39751211140134154172026758035355:code]
|
|
[{_}
|
|
[ {{10000@(113.42.0) [s0;%% [*@7;4 Thread synchronization primitives]]}}&]
|
|
[s0; &]
|
|
[ {{10000t/25b/25@1 [s0; [* Function List]]}}&]
|
|
[s4; &]
|
|
[s5;:AssertST`(`): [@(0.0.255) void]_[* AssertST]()&]
|
|
[s2;%% This operation can be used only DEBUG mode. If any Thread
|
|
was started prior to calling AssertST, it will stop the execution
|
|
with diagnostic message. The purpose is that some global initialization
|
|
routines are best performed before any multi`-threading starts.
|
|
AssertST can be used to assure this as runtime check.&]
|
|
[s3;%% &]
|
|
[s4; &]
|
|
[s5;:ReadMemoryBarrier`(`): [@(0.0.255) void]_[* ReadMemoryBarrier]()&]
|
|
[s2;%% Read memory barrier. CPU and compiler is instructed not to
|
|
do any loads ahead of ReadMemoryBarrier (which normally happens
|
|
in out`-of`-order CPUs and can also be a result of compiler optimizations).
|
|
See [^http`:`/`/www`.linuxjournal`.com`/article`/8211^ this] or
|
|
[^http`:`/`/en`.wikipedia`.org`/wiki`/Memory`_barrier^ this] for
|
|
more detailed description of problem.&]
|
|
[s3; &]
|
|
[s4; &]
|
|
[s5;:WriteMemoryBarrier`(`): [@(0.0.255) void]_[* WriteMemoryBarrier]()&]
|
|
[s2;%% Write memory barrier. CPU and compiler is instructed not to
|
|
do any writes ahead of WriteMemoryBarrier (which normally happens
|
|
in out`-of`-order CPUs and can also be a result of compiler optimizations).
|
|
See [^http`:`/`/www`.linuxjournal`.com`/article`/8211^ this] or
|
|
[^http`:`/`/en`.wikipedia`.org`/wiki`/Memory`_barrier^ this] for
|
|
more detailed description of problem.&]
|
|
[s3; &]
|
|
[s4; &]
|
|
[s5;:ReadWithBarrier`(const volatile U`&`): [@(0.0.255) template]_<[@(0.0.255) class]_[*@4 U
|
|
][@(0.0.255) >]_[*@4 U]_[* ReadWithBarrier]([@(0.0.255) const]_[@(0.0.255) volatile]_[*@4 U][@(0.0.255) `&
|
|
]_[*@3 b])&]
|
|
[s2;%% This template reads the value of [%-*@3 b ](to temporary variable)
|
|
and then invokes ReadMemoryBarrier. The value is returned. This
|
|
assures that the value read is not affected by compiler or CPU
|
|
load reorders. In other words, no read that is after the point
|
|
of the function call can be performed before calling it.&]
|
|
[s3; &]
|
|
[s4; &]
|
|
[s5;:BarrierWrite`(volatile U`&`,V`): [@(0.0.255) template]_<[@(0.0.255) class]_[*@4 U],
|
|
[@(0.0.255) class]_[*@4 V][@(0.0.255) >]_[@(0.0.255) void]_[* BarrierWrite]([@(0.0.255) volat
|
|
ile]_[*@4 U][@(0.0.255) `&]_[*@3 dest], [*@4 V]_[*@3 data])&]
|
|
[s2;%% Invokes WriteMemoryBarier and then writes [%-*@3 data].to [%-*@3 dest].
|
|
This assures that write is not affected by compiler or CPU reorders.
|
|
In other words, no write that is after the point of the function
|
|
call can be performed before calling it.&]
|
|
[s3;%% &]
|
|
[s4; &]
|
|
[s5;:Atomic`:`:typedef: [@(0.0.255) typedef]_[/ integer`_type]_[* Atomic]&]
|
|
[s2;%% This is the integer type that can be used as argument of AtomicXAdd
|
|
function. It is compatible with `'int`' `- it has the same value
|
|
range and it can be converted to `'int`'.&]
|
|
[s0;%% &]
|
|
[s4; &]
|
|
[s5;:AtomicXAdd`(volatile Atomic`&`,int`): [@(0.0.255) int]_[* AtomicXAdd]([@(0.0.255) vola
|
|
tile]_[_^Atomic^ Atomic][@(0.0.255) `&]_[*@3 t], [@(0.0.255) int]_[*@3 incr])&]
|
|
[s2;%% Adds [%-*@3 incr] to atomic variable [%-*@3 t ]and returns the
|
|
original value of [%-*@3 t]. The operation is atomic `- it behaves
|
|
as it would be serialized by Mutex, but is significantly cheaper
|
|
in terms of CPU cycles and memory requirements (no Mutex really
|
|
required...).&]
|
|
[s3; &]
|
|
[s4; &]
|
|
[s5;:AtomicInc`(volatile Atomic`&`): [@(0.0.255) int]_[* AtomicInc]([@(0.0.255) volatile]_[_^Atomic^ A
|
|
tomic][@(0.0.255) `&]_[*@3 t])&]
|
|
[s2;%% Same as AtomicXAdd(t, `+1) `+ 1.&]
|
|
[s3;%% &]
|
|
[s4; &]
|
|
[s5;:AtomicDec`(volatile Atomic`&`): [@(0.0.255) int]_[* AtomicDec]([@(0.0.255) volatile]_[_^Atomic^ A
|
|
tomic][@(0.0.255) `&]_[*@3 t])&]
|
|
[s2;%% Same as AtomicXAdd(t, `-1) `- 1.&]
|
|
[s3;%% &]
|
|
[s4; &]
|
|
[s5;:AtomicRead`(const volatile Atomic`&`): [@(0.0.255) int]_[* AtomicRead]([@(0.0.255) con
|
|
st]_[@(0.0.255) volatile]_[_^Atomic^ Atomic][@(0.0.255) `&]_[*@3 t])&]
|
|
[s2;%% Same as ReadWithBarrier(t).&]
|
|
[s3;%% &]
|
|
[s4; &]
|
|
[s5;:AtomicWrite`(volatile Atomic`&`,int`): [@(0.0.255) void]_[* AtomicWrite]([@(0.0.255) v
|
|
olatile]_[_^Atomic^ Atomic][@(0.0.255) `&]_[*@3 t], [@(0.0.255) int]_[*@3 val])&]
|
|
[s2;%% Same as BarrierWrite(t, val).&]
|
|
[s0; &]
|
|
[ {{10000t/25b/25@1 [s0; [* Macro List]]}}&]
|
|
[s4; &]
|
|
[s5;:INTERLOCKED: [* INTERLOCKED]&]
|
|
[s2;%% This macro adds static Mutex to the block. For example:&]
|
|
[s10;%% -|INTERLOCKED `{&]
|
|
[s10;%% -|-|Foo();&]
|
|
[s10;%% -|`}&]
|
|
[s0;%% -|is equivalent to&]
|
|
[s10;%% -|`{-|static StaticMutex [/ uniquename];&]
|
|
[s10;%% -|-|[/ uniquename].Enter();&]
|
|
[s10;%% -|-|Foo();&]
|
|
[s10;%% -|-|[/ uniquename].Leave();&]
|
|
[s10;%% -|`}&]
|
|
[s3; &]
|
|
[s4; &]
|
|
[s5;:INTERLOCKED`_`(cs`): [* INTERLOCKED`_]([*@3 cs])&]
|
|
[s2;%% Similar to INTERLOCKED, but instead of `'anonymous`' implicit
|
|
static Mutex it uses explicit Mutex [%-*@3 cs].&]
|
|
[s3;%% &]
|
|
[s4; &]
|
|
[s5;:ONCELOCK: [* ONCELOCK]&]
|
|
[s2;%% Designates block that only gets performed at first run, taking
|
|
into account all multi`-threading issues. In single threaded
|
|
environment&]
|
|
[s10;%% -|ONCELOCK `{ Foo(); `}&]
|
|
[s0;%% -|is equivalent to&]
|
|
[s10;%% -|`{ static bool x; if(!x) `{ x `= true; Foo(); `} `}.&]
|
|
[s3; &]
|
|
[s4; &]
|
|
[s5;:ONCELOCK`_`(o`_b`_`): [* ONCELOCK`_]([*@3 o`_b`_])&]
|
|
[s2;%% Similar to ONCELOCK, but using explicitly defined control
|
|
variable.&]
|
|
[s3;%% &]
|
|
[s4; &]
|
|
[s5;:ONCELOCK`_PTR`(ptr`, init`): [* ONCELOCK`_PTR]([*@3 ptr], [*@3 init])&]
|
|
[s2;%% This special construction can be used to initialize a value
|
|
of arbitrary pointer with expression. Initially, [%-*@3 ptr] is
|
|
NULL, [%-*@3 init] should return a non`-NULL value assignable to
|
|
[%-*@3 ptr]. Value is initialized only once and only in that case
|
|
[%-*@3 init] is evaluated. After that (when [%-*@3 ptr] is non`-NULL)
|
|
only ReadMemoryBarrier synchronization primitive is used to check
|
|
the [%-*@3 ptr], making the operation relatively fast.&]
|
|
[s0; ] |