Skip to content

Commit 37ada97

Browse files
committed
AtomicMarkableReference: Add initial specs
1 parent 9f897f3 commit 37ada97

File tree

1 file changed

+165
-0
lines changed

1 file changed

+165
-0
lines changed
Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
# Concurrent::AtomicMarkableReference;w
2+
shared_examples :atomic_markable_reference do
3+
# use a number outside JRuby's fixnum cache range, to ensure identity is
4+
# preserved
5+
let(:atomic) { Concurrent::AtomicMarkableReference.new(1000, true) }
6+
7+
specify :test_construct do
8+
expect(atomic.value).to eq 1000
9+
expect(atomic.marked?).to eq true
10+
end
11+
12+
specify :test_set do
13+
res = atomic.set(1001, true)
14+
15+
expect(atomic.value).to eq 1001
16+
expect(atomic.marked).to eq true
17+
expect(res).to eq [1001, true]
18+
end
19+
20+
specify :test_update do
21+
res = atomic.update { |v, m| [v + 1, !m] }
22+
23+
expect(atomic.marked?).to eq false
24+
expect(atomic.get_reference).to eq 1001
25+
expect(res).to eq [1001, false]
26+
end
27+
28+
specify :test_try_update do
29+
res = atomic.try_update { |v, m| [v + 1, !m] }
30+
31+
expect(atomic.value).to eq 1001
32+
expect(res).to eq [1001, false]
33+
end
34+
35+
specify :test_try_update_fails do
36+
expect do
37+
# assigning within block exploits implementation detail for test
38+
atomic.try_update do |v, m|
39+
atomic.set(1001, false)
40+
[v + 1, !m]
41+
end
42+
end.to raise_error Concurrent::ConcurrentUpdateError
43+
end
44+
45+
specify :test_update_retries do
46+
tries = 0
47+
48+
# assigning within block exploits implementation detail for test
49+
atomic.update do |v, m|
50+
tries += 1
51+
atomic.set(1001, false)
52+
[v + 1, !m]
53+
end
54+
55+
expect(tries).to eq 2
56+
end
57+
58+
specify :test_numeric_cas do
59+
# non-idempotent Float (JRuby, Rubinius, MRI < 2.0.0 or 32-bit)
60+
atomic.set(1.0 + 0.1, true)
61+
expect(atomic.compare_and_set(1.0 + 0.1, 1.2, true, false))
62+
.to be_truthy, "CAS failed for (#{1.0 + 0.1}, true) => (1.2, false)"
63+
64+
# Bignum
65+
atomic.set(2**100, false)
66+
expect(atomic.compare_and_set(2**100, 0, false, true))
67+
.to be_truthy, "CAS failed for (#{2**100}, false) => (0, true)"
68+
69+
# Rational
70+
require 'rational' unless ''.respond_to? :to_r
71+
atomic.set(Rational(1, 3), true)
72+
expect(atomic.compare_and_set(Rational(1, 3), 0, true, false))
73+
.to be_truthy, "CAS failed for (#{Rational(1, 3)}, true) => (0, false)"
74+
75+
# Complex
76+
require 'complex' unless ''.respond_to? :to_c
77+
atomic.set(Complex(1, 2), false)
78+
expect(atomic.compare_and_set(Complex(1, 2), 0, false, true))
79+
.to be_truthy, "CAS failed for (#{Complex(1, 2)}, false) => (0, false)"
80+
end
81+
end
82+
83+
# Specs for platform specific implementations
84+
module Concurrent
85+
describe AtomicMarkableReference do
86+
it_should_behave_like :atomic_markable_reference
87+
end
88+
89+
describe MutexAtomicMarkableReference do
90+
it_should_behave_like :atomic_markable_reference
91+
end
92+
93+
if defined? Concurrent::CAtomicMarkableReference
94+
describe CAtomicMarkableReference do
95+
skip 'Unimplemented'
96+
end
97+
elsif defined? Concurrent::JavaAtomicMarkableReference
98+
describe JavaAtomicMarkableReference do
99+
skip 'Unimplemented'
100+
end
101+
elsif defined? Concurrent::RbxAtomicMarkableReference
102+
describe RbxAtomicMarkableReference do
103+
skip 'Unimplemented'
104+
end
105+
end
106+
107+
describe AtomicMarkableReference do
108+
if Concurrent.on_jruby?
109+
it 'inherits from JavaAtomicMarkableReference' do
110+
skip 'Unimplemented'
111+
end
112+
elsif Concurrent.allow_c_extensions?
113+
it 'inherits from CAtomicMarkableReference' do
114+
skip 'Unimplemented'
115+
end
116+
elsif Concurrent.on_rbx?
117+
it 'inherits from RbxAtomicMarkableReference' do
118+
skip 'Unimplemented'
119+
end
120+
else
121+
it 'inherits from MutexAtomicMarkableReference' do
122+
skip 'Unimplemented'
123+
end
124+
end
125+
end
126+
127+
describe MutexAtomicMarkableReference do
128+
it_should_behave_like :atomic_markable_reference
129+
end
130+
131+
if defined? Concurrent::CAtomicMarkableReference
132+
describe CAtomicMarkableReference do
133+
skip 'Unimplemented'
134+
end
135+
elsif defined? Concurrent::JavaAtomicMarkableReference
136+
describe JavaAtomicMarkableReference do
137+
skip 'Unimplemented'
138+
end
139+
elsif defined? Concurrent::RbxAtomicMarkableReference
140+
describe RbxAtomicMarkableReference do
141+
skip 'Unimplemented'
142+
end
143+
end
144+
145+
describe AtomicMarkableReference do
146+
if Concurrent.on_jruby?
147+
it 'inherits from JavaAtomicMarkableReference' do
148+
skip 'Unimplemented'
149+
end
150+
elsif Concurrent.allow_c_extensions?
151+
it 'inherits from CAtomicMarkableReference' do
152+
skip 'Unimplemented'
153+
end
154+
elsif Concurrent.on_rbx?
155+
it 'inherits from RbxAtomicMarkableReference' do
156+
skip 'Unimplemented'
157+
end
158+
else
159+
it 'inherits from MutexAtomicMarkableReference' do
160+
expect(AtomicMarkableReference.ancestors)
161+
.to include(Concurrent::MutexAtomicMarkableReference)
162+
end
163+
end
164+
end
165+
end

0 commit comments

Comments
 (0)