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 
17 class AtomicHelper {
18     static void store(T)(ref T stuff, T newVal) {
19         core.atomic.atomicStore(*(cast(shared)&stuff), cast(shared)newVal);
20     }
21 
22     static T load(T)(ref T val) {
23         return core.atomic.atomicLoad(*(cast(shared)&val));
24     }
25 
26     static bool compareAndSet(T, V1, V2)(ref T stuff, V1 testVal, lazy V2 newVal) {
27         static if(is(T == interface)) {
28             import hunt.util.Common;
29             static if(CompilerHelper.isGreaterThan(2089)) {
30                 return core.atomic.cas(cast(Object*)&stuff, cast(Object)testVal, cast(Object)newVal);
31             } else {
32             // FIXME: Needing refactor or cleanup -@zhangxueping at 2019-12-17T13:52:10+08:00
33             // More tests needed
34                 return core.atomic.cas(cast(shared)&stuff, cast(shared)testVal, cast(shared)newVal);
35             }
36         } else {
37             return core.atomic.cas(cast(shared)&stuff, cast(shared)testVal, cast(shared)newVal);
38         }
39         // return core.atomic.cas(cast(shared)&stuff, testVal, newVal);
40     }
41 
42     static T increment(T, U)(ref T stuff, U delta = 1) if (__traits(isIntegral, T)) {
43         return core.atomic.atomicOp!("+=")(stuff, delta);
44     }
45 
46     static T decrement(T, U)(ref T stuff, U delta = 1) if (__traits(isIntegral, T)) {
47         return core.atomic.atomicOp!("-=")(stuff, delta);
48     }
49 
50     static T getAndAdd(T, U)(ref T stuff, U delta) {
51         T v = increment(stuff, delta);
52         return v - delta;
53     }
54 
55     static T getAndSet(T, U)(ref T stuff, U newValue) 
56             if(__traits( compiles, { stuff = newValue; } )) {
57         static if(CompilerHelper.isGreaterThan(2088)) {
58             return cast(T)atomicExchange(cast(shared)&stuff, cast(shared)newValue);
59         } else {
60             T v = stuff;
61             store(stuff, newValue);
62             return v;            
63         }
64     }
65 
66     static T getAndBitwiseOr(T, U)(ref T stuff, U value) {
67         T v = stuff;
68         core.atomic.atomicOp!("|=")(stuff, value);
69         return v;
70     }
71 
72     static T getAndIncrement(T)(ref T stuff) {
73         return getAndAdd(stuff, 1);
74     }
75 
76     static T getAndDecrement(T)(ref T stuff) {
77         return getAndAdd(stuff, -1);
78     }
79 }
80 
81 alias store = AtomicHelper.store;
82 alias load = AtomicHelper.load;
83 alias compareAndSet = AtomicHelper.compareAndSet;
84 alias increment = AtomicHelper.increment;
85 alias decrement = AtomicHelper.decrement;
86