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
|
require 'rbconfig'
module Concurrent
require 'concurrent/atomic/thread_local_var'
RSpec.describe ThreadLocalVar do
context '#initialize' do
it 'can set an initial value' do
v = described_class.new(14)
expect(v.value).to eq 14
end
it 'sets nil as a default initial value' do
v = described_class.new
expect(v.value).to be_nil
end
it 'sets the same initial value for all threads' do
v = described_class.new(14)
t1 = in_thread { v.value }
t2 = in_thread { v.value }
expect(t1.value).to eq 14
expect(t2.value).to eq 14
end
if Concurrent.on_jruby?
it 'extends JavaThreadLocalVar' do
expect(described_class.ancestors).to include(Concurrent::JavaThreadLocalVar)
end
else
it 'extends RubyThreadLocalVar' do
expect(described_class.ancestors).to include(Concurrent::RubyThreadLocalVar)
end
end
it 'can set a block to be called to get the initial value' do
v = described_class.new { 14 }
expect(v.value).to eq 14
end
context 'when attempting to set both an initial value and a block' do
it do
expect { described_class.new(14) { 14 } }.to raise_error(ArgumentError)
end
end
end
context '#value' do
let(:v) { described_class.new(14) }
it 'returns the current value' do
expect(v.value).to eq 14
end
it 'returns the value after modification' do
v.value = 2
expect(v.value).to eq 2
end
context 'when using a block to initialize the value' do
it 'calls the block to initialize the value' do
block = proc { }
expect(block).to receive(:call)
v = described_class.new(&block)
v.value
end
it 'sets the block return value as the current value' do
value = 13
v = described_class.new { value += 1 }
v.value
expect(v.value).to be 14
end
it 'calls the block to initialize the value for each thread' do
block = proc { }
expect(block).to receive(:call).twice
v = described_class.new(&block)
in_thread { v.value }.join
in_thread { v.value }.join
end
end
end
context '#value=' do
let(:v) { described_class.new(14) }
it 'sets a new value' do
v.value = 2
expect(v.value).to eq 2
end
it 'returns the new value' do
expect(v.value = 2).to eq 2
end
it 'does not modify the initial value for other threads' do
v.value = 2
t = in_thread { v.value }
expect(t.value).to eq 14
end
it 'does not modify the value for other threads' do
v.value = 2
b1 = CountDownLatch.new(2)
b2 = CountDownLatch.new(2)
t1 = in_thread do
b1.count_down
b1.wait
v.value = 1
b2.count_down
b2.wait
v.value
end
t2 = in_thread do
b1.count_down
b1.wait
v.value = 2
b2.count_down
b2.wait
v.value
end
expect(t1.value).to eq 1
expect(t2.value).to eq 2
end
end
end
end
|