|
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