|
1 | 1 | module Concurrent
|
2 | 2 |
|
3 |
| - describe Synchronization::Object do |
| 3 | + describe Synchronization do |
| 4 | + describe Synchronization::Object do |
4 | 5 |
|
5 |
| - class AClass < Synchronization::Object |
6 |
| - attr_volatile :volatile |
7 |
| - attr_accessor :not_volatile |
| 6 | + class AClass < Synchronization::Object |
| 7 | + attr_volatile :volatile |
| 8 | + attr_accessor :not_volatile |
8 | 9 |
|
9 |
| - def initialize(value = nil) |
10 |
| - super() |
11 |
| - @Final = value |
12 |
| - ensure_ivar_visibility! |
13 |
| - end |
| 10 | + def initialize(value = nil) |
| 11 | + super() |
| 12 | + @Final = value |
| 13 | + ensure_ivar_visibility! |
| 14 | + end |
14 | 15 |
|
15 |
| - def final |
16 |
| - @Final |
17 |
| - end |
| 16 | + def final |
| 17 | + @Final |
| 18 | + end |
18 | 19 |
|
19 |
| - def count |
20 |
| - synchronize { @count += 1 } |
21 |
| - end |
| 20 | + def count |
| 21 | + synchronize { @count += 1 } |
| 22 | + end |
22 | 23 |
|
23 |
| - def wait(timeout = nil) |
24 |
| - synchronize { ns_wait(timeout) } |
25 |
| - end |
| 24 | + def wait(timeout = nil) |
| 25 | + synchronize { ns_wait(timeout) } |
| 26 | + end |
26 | 27 |
|
27 |
| - private |
| 28 | + private |
28 | 29 |
|
29 |
| - def ns_initialize |
30 |
| - @count = 0 |
| 30 | + def ns_initialize |
| 31 | + @count = 0 |
| 32 | + end |
31 | 33 | end
|
32 |
| - end |
33 | 34 |
|
34 |
| - subject { AClass.new } |
| 35 | + subject { AClass.new } |
35 | 36 |
|
36 |
| - describe '#wait' do |
| 37 | + describe '#wait' do |
37 | 38 |
|
38 |
| - it 'waiting thread is sleeping' do |
39 |
| - t = Thread.new do |
40 |
| - Thread.abort_on_exception = true |
41 |
| - subject.wait |
| 39 | + it 'waiting thread is sleeping' do |
| 40 | + t = Thread.new do |
| 41 | + Thread.abort_on_exception = true |
| 42 | + subject.wait |
| 43 | + end |
| 44 | + sleep 0.1 |
| 45 | + expect(t.status).to eq 'sleep' |
42 | 46 | end
|
43 |
| - sleep 0.1 |
44 |
| - expect(t.status).to eq 'sleep' |
45 |
| - end |
46 | 47 |
|
47 |
| - it 'sleeping thread can be killed' do |
48 |
| - t = Thread.new do |
49 |
| - Thread.abort_on_exception = true |
50 |
| - subject.wait rescue nil |
| 48 | + it 'sleeping thread can be killed' do |
| 49 | + t = Thread.new do |
| 50 | + Thread.abort_on_exception = true |
| 51 | + subject.wait rescue nil |
| 52 | + end |
| 53 | + sleep 0.1 |
| 54 | + t.kill |
| 55 | + sleep 0.1 |
| 56 | + expect(t.status).to eq false |
| 57 | + expect(t.alive?).to eq false |
51 | 58 | end
|
52 |
| - sleep 0.1 |
53 |
| - t.kill |
54 |
| - sleep 0.1 |
55 |
| - expect(t.status).to eq false |
56 |
| - expect(t.alive?).to eq false |
57 | 59 | end
|
58 |
| - end |
59 | 60 |
|
60 |
| - describe '#synchronize' do |
61 |
| - it 'allows only one thread to execute count' do |
62 |
| - threads = 10.times.map { Thread.new(subject) { 100.times { subject.count } } } |
63 |
| - threads.each(&:join) |
64 |
| - expect(subject.count).to eq 1001 |
| 61 | + describe '#synchronize' do |
| 62 | + it 'allows only one thread to execute count' do |
| 63 | + threads = 10.times.map { Thread.new(subject) { 100.times { subject.count } } } |
| 64 | + threads.each(&:join) |
| 65 | + expect(subject.count).to eq 1001 |
| 66 | + end |
65 | 67 | end
|
66 |
| - end |
67 | 68 |
|
68 |
| - describe 'signaling' do |
69 |
| - pending 'for now pending, tested pretty well by Event' |
70 |
| - end |
| 69 | + describe 'signaling' do |
| 70 | + pending 'for now pending, tested pretty well by Event' |
| 71 | + end |
71 | 72 |
|
72 |
| - specify 'final field always visible' do |
73 |
| - store = AClass.new 'asd' |
74 |
| - t1 = Thread.new { 1000000000.times { |i| store = AClass.new i.to_s } } |
75 |
| - t2 = Thread.new { 10.times { expect(store.final).not_to be_nil; Thread.pass } } |
76 |
| - t2.join |
77 |
| - t1.kill |
78 |
| - end |
| 73 | + specify 'final field always visible' do |
| 74 | + store = AClass.new 'asd' |
| 75 | + t1 = Thread.new { 1000000000.times { |i| store = AClass.new i.to_s } } |
| 76 | + t2 = Thread.new { 10.times { expect(store.final).not_to be_nil; Thread.pass } } |
| 77 | + t2.join |
| 78 | + t1.kill |
| 79 | + end |
79 | 80 |
|
80 |
| - describe 'attr volatile' do |
81 |
| - specify 'older writes are always visible' do |
82 |
| - store = AClass.new |
83 |
| - store.not_volatile = 0 |
84 |
| - store.volatile = 0 |
85 |
| - |
86 |
| - t1 = Thread.new do |
87 |
| - Thread.abort_on_exception = true |
88 |
| - 1000000000.times do |i| |
89 |
| - store.not_volatile = i |
90 |
| - store.volatile = i |
| 81 | + describe 'attr volatile' do |
| 82 | + specify 'older writes are always visible' do |
| 83 | + store = AClass.new |
| 84 | + store.not_volatile = 0 |
| 85 | + store.volatile = 0 |
| 86 | + |
| 87 | + t1 = Thread.new do |
| 88 | + Thread.abort_on_exception = true |
| 89 | + 1000000000.times do |i| |
| 90 | + store.not_volatile = i |
| 91 | + store.volatile = i |
| 92 | + end |
91 | 93 | end
|
92 |
| - end |
93 | 94 |
|
94 |
| - t2 = Thread.new do |
95 |
| - 10.times do |
96 |
| - volatile = store.volatile |
97 |
| - not_volatile = store.not_volatile |
98 |
| - expect(not_volatile).to be >= volatile |
99 |
| - Thread.pass |
| 95 | + t2 = Thread.new do |
| 96 | + 10.times do |
| 97 | + volatile = store.volatile |
| 98 | + not_volatile = store.not_volatile |
| 99 | + expect(not_volatile).to be >= volatile |
| 100 | + Thread.pass |
| 101 | + end |
100 | 102 | end
|
101 |
| - end |
102 | 103 |
|
103 |
| - t2.join |
104 |
| - t1.kill |
| 104 | + t2.join |
| 105 | + t1.kill |
| 106 | + end |
105 | 107 | end
|
106 | 108 | end
|
107 | 109 |
|
108 | 110 | describe Synchronization::ImmutableStruct do
|
109 |
| - let(:klass) { described_class.with_fields(:a, :b) } |
110 |
| - subject { klass[1, 'a'] } |
| 111 | + AB = described_class.with_fields(:a, :b) |
| 112 | + subject { AB[1, 'a'] } |
111 | 113 |
|
112 | 114 | specify do
|
113 |
| - expect(klass.superclass).to eq described_class |
| 115 | + expect(AB.superclass).to eq described_class |
114 | 116 | expect(subject.a).to eq 1
|
115 | 117 | expect(subject.b).to eq 'a'
|
| 118 | + expect(subject.values).to eq [1, 'a'] |
| 119 | + expect(subject.to_a).to eq [1, 'a'] |
| 120 | + expect(subject.size).to eq 2 |
| 121 | + expect(subject.members).to eq [:a, :b] |
| 122 | + expect(subject.each.to_a).to eq [[:a, 1], [:b, 'a']] |
| 123 | + expect(subject.inspect).to match /#<Concurrent::AB:0x[\da-f]+ (@a=1|@b="a"), (@a=1|@b="a")>/ |
| 124 | + end |
| 125 | + |
| 126 | + specify 'equality' do |
| 127 | + klass = described_class.with_fields(:a, :b) |
| 128 | + expect(klass[1, 'a']).not_to be == klass[1, 'a'] |
| 129 | + klass.define_equality! |
| 130 | + expect(klass[1, 'a']).to be == klass[1, 'a'] |
116 | 131 | end
|
117 | 132 | end
|
118 | 133 |
|
|
0 commit comments