1 /*
2  * Hunt - A refined core library for D programming language.
3  *
4  * Copyright (C) 2018-2019 HuntLabs
5  *
6  * Website: https://www.huntlabs.net/
7  *
8  * Licensed under the Apache-2.0 License.
9  *
10  */
11 
12 module hunt.concurrency.atomic.AtomicHelper;
13 
14 import core.atomic;
15 import hunt.util.Common;
16 import hunt.util.CompilerHelper;
17 
18 class AtomicHelper {
19     static void store(T)(ref T stuff, T newVal) {
20         core.atomic.atomicStore(*(cast(shared)&stuff), cast(shared)newVal);
21     }
22 
23     static T load(T)(ref T val) {
24         return core.atomic.atomicLoad(*(cast(shared)&val));
25     }
26 
27     static bool compareAndSet(T, V1, V2)(ref T stuff, V1 testVal, lazy V2 newVal) {
28         static if(is(T == interface)) {
29             import hunt.util.Common;
30             static if(CompilerHelper.isGreaterThan(2089)) {
31                 return core.atomic.cas(cast(Object*)&stuff, cast(Object)testVal, cast(Object)newVal);
32             } else {
33             // FIXME: Needing refactor or cleanup -@zhangxueping at 2019-12-17T13:52:10+08:00
34             // More tests needed
35                 return core.atomic.cas(cast(shared)&stuff, cast(shared)testVal, cast(shared)newVal);
36             }
37         } else {
38             return core.atomic.cas(cast(shared)&stuff, cast(shared)testVal, cast(shared)newVal);
39         }
40         // return core.atomic.cas(cast(shared)&stuff, testVal, newVal);
41     }
42 
43     static T increment(T, U)(ref T stuff, U delta = 1) if (__traits(isIntegral, T)) {
44         return core.atomic.atomicOp!("+=")(stuff, delta);
45     }
46 
47     static T decrement(T, U)(ref T stuff, U delta = 1) if (__traits(isIntegral, T)) {
48         return core.atomic.atomicOp!("-=")(stuff, delta);
49     }
50 
51     static T getAndAdd(T, U)(ref T stuff, U delta) {
52         T v = increment(stuff, delta);
53         return v - delta;
54     }
55 
56     static T getAndSet(T, U)(ref T stuff, U newValue) 
57             if(__traits( compiles, { stuff = newValue; } )) {
58         static if(CompilerHelper.isGreaterThan(2088)) {
59             return cast(T)atomicExchange(cast(shared)&stuff, cast(shared)newValue);
60         } else {
61             T v = stuff;
62             store(stuff, newValue);
63             return v;            
64         }
65     }
66 
67     static T getAndBitwiseOr(T, U)(ref T stuff, U value) {
68         T v = stuff;
69         core.atomic.atomicOp!("|=")(stuff, value);
70         return v;
71     }
72 
73     static T getAndIncrement(T)(ref T stuff) {
74         return getAndAdd(stuff, 1);
75     }
76 
77     static T getAndDecrement(T)(ref T stuff) {
78         return getAndAdd(stuff, -1);
79     }
80 }
81 
82 alias store = AtomicHelper.store;
83 alias load = AtomicHelper.load;
84 alias compareAndSet = AtomicHelper.compareAndSet;
85 alias increment = AtomicHelper.increment;
86 alias decrement = AtomicHelper.decrement;
87