Skip to content

Commit 34ae02d

Browse files
authored
Merge pull request #741 from ruby-concurrency/pitr-ch/delay
Raise on recursive Delay#value call
2 parents 835509c + e3d5175 commit 34ae02d

File tree

2 files changed

+20
-6
lines changed

2 files changed

+20
-6
lines changed

lib/concurrent/delay.rb

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -81,13 +81,15 @@ def value(timeout = nil)
8181
# this function has been optimized for performance and
8282
# should not be modified without running new benchmarks
8383
synchronize do
84-
execute = @computing = true unless @computing
84+
execute = @evaluation_started = true unless @evaluation_started
8585
if execute
8686
begin
8787
set_state(true, @task.call, nil)
8888
rescue => ex
8989
set_state(false, nil, ex)
9090
end
91+
elsif incomplete?
92+
raise IllegalOperationError, 'Recursive call to #value during evaluation of the Delay'
9193
end
9294
end
9395
if @do_nothing_on_deref
@@ -144,7 +146,7 @@ def wait(timeout = nil)
144146
def reconfigure(&block)
145147
synchronize do
146148
raise ArgumentError.new('no block given') unless block_given?
147-
unless @computing
149+
unless @evaluation_started
148150
@task = block
149151
true
150152
else
@@ -160,9 +162,9 @@ def ns_initialize(opts, &block)
160162
set_deref_options(opts)
161163
@executor = opts[:executor]
162164

163-
@task = block
164-
@state = :pending
165-
@computing = false
165+
@task = block
166+
@state = :pending
167+
@evaluation_started = false
166168
end
167169

168170
private
@@ -173,7 +175,7 @@ def execute_task_once # :nodoc:
173175
# should not be modified without running new benchmarks
174176
execute = task = nil
175177
synchronize do
176-
execute = @computing = true unless @computing
178+
execute = @evaluation_started = true unless @evaluation_started
177179
task = @task
178180
end
179181

spec/concurrent/delay_spec.rb

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,18 @@ def dereferenceable_subject(value, opts = {})
8585
delay = Delay.new(&task)
8686
5.times{ delay.value }
8787
end
88+
89+
it 'raises when called recursively' do
90+
delay = Delay.new { delay.value }
91+
expect { delay.value! }.to raise_error(IllegalOperationError)
92+
expect(delay.reason).to be_a_kind_of(IllegalOperationError)
93+
end
94+
95+
it 'can be called twice' do
96+
delay = Delay.new { 10 }
97+
expect(delay.value).to eq 10
98+
expect(delay.value).to eq 10
99+
end
88100
end
89101
end
90102
end

0 commit comments

Comments
 (0)