Skip to content

Commit 084df29

Browse files
committed
MVar#take accepts a block as parameter
1 parent 9c5b03a commit 084df29

File tree

2 files changed

+30
-4
lines changed

2 files changed

+30
-4
lines changed

lib/concurrent/mvar.rb

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -68,10 +68,14 @@ def take(timeout = nil)
6868

6969
# If we timed out we'll still be empty
7070
if unlocked_full?
71-
value = @value
72-
@value = EMPTY
73-
@empty_condition.signal
74-
apply_deref_options(value)
71+
if block_given?
72+
yield @value
73+
else
74+
value = @value
75+
@value = EMPTY
76+
@empty_condition.signal
77+
apply_deref_options(value)
78+
end
7579
else
7680
TIMEOUT
7781
end

spec/concurrent/mvar_spec.rb

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,28 @@ def dereferenceable_subject(value, opts = {})
6868
expect(m.take(0.1)).to eq MVar::TIMEOUT
6969
end
7070

71+
context 'when a block is given' do
72+
it 'yields current value to the block and puts back value' do
73+
m = MVar.new(14)
74+
expect { |b| m.take(&b) }.to yield_with_args(14)
75+
expect(m.take).to eq(14)
76+
end
77+
it 'puts back value even if an exception is raised' do
78+
m = MVar.new(14)
79+
expect { m.take { fail 'boom!' } }.to raise_error('boom!')
80+
expect(m.take).to eq(14)
81+
end
82+
it 'returns the returned value of the block' do
83+
m = MVar.new(14)
84+
expect(m.take{2}).to eq(2)
85+
expect(m.take).to eq(14)
86+
end
87+
it 'returns TIMEOUT on timeout on an empty MVar' do
88+
m = MVar.new
89+
expect(m.take(0.1){}).to eq MVar::TIMEOUT
90+
end
91+
end
92+
7193
end
7294

7395
describe '#put' do

0 commit comments

Comments
 (0)