|
3 | 3 | module Concurrent
|
4 | 4 |
|
5 | 5 | describe Synchronization do
|
| 6 | + |
| 7 | + shared_examples :attr_volatile do |
| 8 | + |
| 9 | + specify 'older writes are always visible' do |
| 10 | + # store = BClass.new |
| 11 | + store.not_volatile = 0 |
| 12 | + store.volatile = 0 |
| 13 | + |
| 14 | + t1 = Thread.new do |
| 15 | + Thread.abort_on_exception = true |
| 16 | + 1000000000.times do |i| |
| 17 | + store.not_volatile = i |
| 18 | + store.volatile = i |
| 19 | + end |
| 20 | + end |
| 21 | + |
| 22 | + t2 = Thread.new do |
| 23 | + 10.times do |
| 24 | + volatile = store.volatile |
| 25 | + not_volatile = store.not_volatile |
| 26 | + expect(not_volatile).to be >= volatile |
| 27 | + Thread.pass |
| 28 | + end |
| 29 | + end |
| 30 | + |
| 31 | + t2.join |
| 32 | + t1.kill |
| 33 | + end |
| 34 | + end |
| 35 | + |
6 | 36 | describe Synchronization::Object do
|
7 | 37 | class AAClass < Synchronization::Object
|
8 | 38 | end
|
@@ -40,6 +70,14 @@ class ADClass < ACClass
|
40 | 70 |
|
41 | 71 | # TODO (pitr 12-Sep-2015): give a whole gem a pass to find classes with final fields without using the convention and migrate
|
42 | 72 | Synchronization::Object.ensure_safe_initialization_when_final_fields_are_present
|
| 73 | + |
| 74 | + class VolatileFieldClass < Synchronization::Object |
| 75 | + attr_volatile :volatile |
| 76 | + attr_accessor :not_volatile |
| 77 | + end |
| 78 | + |
| 79 | + let(:store) { VolatileFieldClass.new } |
| 80 | + it_should_behave_like :attr_volatile |
43 | 81 | end
|
44 | 82 |
|
45 | 83 | describe Synchronization::LockableObject do
|
@@ -142,33 +180,21 @@ def ns_initialize
|
142 | 180 | t1.kill
|
143 | 181 | end
|
144 | 182 |
|
145 |
| - describe 'attr volatile' do |
146 |
| - specify 'older writes are always visible' do |
147 |
| - store = BClass.new |
148 |
| - store.not_volatile = 0 |
149 |
| - store.volatile = 0 |
150 |
| - |
151 |
| - t1 = Thread.new do |
152 |
| - Thread.abort_on_exception = true |
153 |
| - 1000000000.times do |i| |
154 |
| - store.not_volatile = i |
155 |
| - store.volatile = i |
156 |
| - end |
157 |
| - end |
| 183 | + let(:store) { BClass.new } |
| 184 | + it_should_behave_like :attr_volatile |
| 185 | + end |
158 | 186 |
|
159 |
| - t2 = Thread.new do |
160 |
| - 10.times do |
161 |
| - volatile = store.volatile |
162 |
| - not_volatile = store.not_volatile |
163 |
| - expect(not_volatile).to be >= volatile |
164 |
| - Thread.pass |
165 |
| - end |
166 |
| - end |
| 187 | + describe 'Concurrent::Synchronization::Volatile module' do |
| 188 | + class BareClass |
| 189 | + include Synchronization::Volatile |
167 | 190 |
|
168 |
| - t2.join |
169 |
| - t1.kill |
170 |
| - end |
| 191 | + attr_volatile :volatile |
| 192 | + attr_accessor :not_volatile |
171 | 193 | end
|
| 194 | + |
| 195 | + let(:store) { BareClass.new } |
| 196 | + it_should_behave_like :attr_volatile |
172 | 197 | end
|
| 198 | + |
173 | 199 | end
|
174 | 200 | end
|
0 commit comments