-
Notifications
You must be signed in to change notification settings - Fork 13
/
Copy pathAtomicBool.hx
174 lines (143 loc) · 3.72 KB
/
AtomicBool.hx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
/*
* SPDX-FileCopyrightText: © Vegard IT GmbH (https://vegardit.com) and contributors
* SPDX-FileContributor: Sebastian Thomschke, Vegard IT GmbH
* SPDX-License-Identifier: Apache-2.0
*/
package hx.concurrent.atomic;
import hx.concurrent.lock.RLock;
#if java
import java.util.concurrent.atomic.AtomicBoolean;
private typedef AB = AtomicBoolean;
#else
private typedef AB = AtomicBoolImpl;
#end
/**
* Boolean with thread-safe atomic operations.
*/
abstract AtomicBool(AB) from AB to AB {
/**
* <pre><code>
* >>> (new AtomicBool() == false) == true
* >>> (new AtomicBool(true) == true) == true
* >>> (new AtomicBool(true) != false) == true
* >>> (!new AtomicBool(true) == false) == true
* </code></pre>
*/
inline //
public function new(val:Bool = false)
this = new AB(val);
@:to inline function toBool():Bool return value;
@:op(!A) inline function op_negate():Bool return !value;
/**
* <pre><code>
* >>> new AtomicBool(true).value == true
* >>> new AtomicBool(false).value == false
* </code></pre>
*/
public var value(get, set):Bool;
inline function get_value():Bool {
#if java
return this.get();
#else
return this.value;
#end
}
inline function set_value(value:Bool):Bool {
this.set(value);
return value;
}
/**
* <pre><code>
* >>> new AtomicBool(true).getAndSet(false) == true
* >>> new AtomicBool(false).getAndSet(true) == false
* </code></pre>
*/
inline //
public function getAndSet(value:Bool):Bool
return this.getAndSet(value);
/**
* <pre><code>
* >>> new AtomicBool(true).negate() == false
* >>> new AtomicBool(false).negate() == true
* </code></pre>
*/
#if !java inline #end
public function negate():Bool {
#if java
var newVal = !this.get();
while (!this.compareAndSet(!newVal, newVal))
newVal = !newVal;
return newVal;
#else
return this.negate();
#end
}
/**
* <pre><code>
* >>> new AtomicBool(true).getAndNegate() == true
* >>> new AtomicBool(false).getAndNegate() == false
* </code></pre>
*/
#if !java inline #end
public function getAndNegate():Bool {
#if java
var oldVal = this.get();
while (!this.compareAndSet(oldVal, !oldVal))
oldVal = !oldVal;
return oldVal;
#else
return this.getAndNegate();
#end
}
/**
* <pre><code>
* >>> new AtomicBool(true).toString() == "true"
* >>> new AtomicBool(false).toString() == "false"
* </code></pre>
*/
inline public function toString():String
return this.toString();
}
private class AtomicBoolImpl {
final _lock = new RLock();
public var value(get, never):Bool;
var _value:Bool;
function get_value():Bool {
_lock.acquire();
final result = _value;
_lock.release();
return result;
}
public function new(initialValue:Bool = false) {
this._value = initialValue;
}
public function getAndSet(value:Bool):Bool {
_lock.acquire();
final old = _value;
_value = value;
_lock.release();
return old;
}
public function getAndNegate():Bool {
_lock.acquire();
final oldValue = _value;
_value = !oldValue;
_lock.release();
return oldValue;
}
public function negate():Bool {
_lock.acquire();
final newValue = !_value;
_value = newValue;
_lock.release();
return newValue;
}
public function set(value:Bool):Void {
_lock.acquire();
this._value = value;
_lock.release();
}
inline //
public function toString()
return Std.string(value);
}