Skip to content

Commit bf54691

Browse files
committed
Allow to be specific about when to continue running
1 parent 661a00d commit bf54691

File tree

2 files changed

+23
-14
lines changed

2 files changed

+23
-14
lines changed

lib/concurrent/promises.rb

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1202,8 +1202,8 @@ def on_rejection_using(executor, *args, &callback)
12021202
# v < 5 ? Promises.future(v, &body) : v
12031203
# end
12041204
# Promises.future(0, &body).run.value! # => 5
1205-
def run
1206-
RunFuturePromise.new_blocked_by1(self, @DefaultExecutor).future
1205+
def run(run_test = method(:run_test) )
1206+
RunFuturePromise.new_blocked_by1(self, @DefaultExecutor, run_test).future
12071207
end
12081208

12091209
# @!visibility private
@@ -1239,6 +1239,10 @@ def to_s
12391239

12401240
private
12411241

1242+
def run_test(v)
1243+
v if v.is_a?(Future)
1244+
end
1245+
12421246
def rejected_resolution(raise_on_reassign, state)
12431247
if raise_on_reassign
12441248
if internal_state == RESERVED
@@ -1303,14 +1307,11 @@ module Resolvable
13031307
# f.resolve true, :val, nil, true if reserved # must be called only if reserved
13041308
# @return [true, false] on successful reservation
13051309
def reserve
1306-
# TODO (pitr-ch 17-Jan-2019): document that the order of the reservation must always be the same
1307-
# TODO (pitr-ch 17-Jan-2019): make only private and expose the atomic stuff?
1308-
# Then it cannot be integrated with other then future stuff :(
1309-
13101310
while true
13111311
return true if compare_and_set_internal_state(PENDING, RESERVED)
13121312
return false if resolved?
1313-
Thread.pass # FIXME (pitr-ch 17-Jan-2019): sleep until given up or resolved instead of busy wait
1313+
# FIXME (pitr-ch 17-Jan-2019): sleep until given up or resolved instead of busy wait
1314+
Thread.pass
13141315
end
13151316
end
13161317

@@ -1354,7 +1355,7 @@ def self.atomic_resolution(resolvable_map)
13541355
end
13551356

13561357
if reserved == sorted.size
1357-
sorted.each { |resolvable, args| resolvable.resolve *args, true, true }
1358+
sorted.each { |resolvable, args| resolvable.resolve(*args, true, true) }
13581359
true
13591360
else
13601361
while reserved > 0
@@ -1974,8 +1975,9 @@ class RunFuturePromise < AbstractFlatPromise
19741975

19751976
private
19761977

1977-
def initialize(delayed, blockers_count, default_executor)
1978+
def initialize(delayed, blockers_count, default_executor, run_test)
19781979
super delayed, 1, Future.new(self, default_executor)
1980+
@RunTest = run_test
19791981
end
19801982

19811983
def process_on_blocker_resolution(future, index)
@@ -1986,11 +1988,12 @@ def process_on_blocker_resolution(future, index)
19861988
return 0
19871989
end
19881990

1989-
value = internal_state.value
1990-
case value
1991-
when Future
1992-
add_delayed_of value
1993-
value.add_callback_notify_blocked self, nil
1991+
value = internal_state.value
1992+
continuation_future = @RunTest.call value
1993+
1994+
if continuation_future
1995+
add_delayed_of continuation_future
1996+
continuation_future.add_callback_notify_blocked self, nil
19941997
else
19951998
resolve_with internal_state
19961999
end

spec/concurrent/promises_spec.rb

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -510,6 +510,12 @@ def behaves_as_delay(delay, value)
510510
v < 5 ? future(v, &body) : raise(v.to_s)
511511
end
512512
expect(future(0, &body).run.reason.message).to eq '5'
513+
514+
body = lambda do |v|
515+
v += 1
516+
v < 5 ? [future(v, &body)] : v
517+
end
518+
expect(future(0, &body).run(-> v { v.first if v.is_a? Array}).value!).to eq 5
513519
end
514520

515521
it 'can be risen when rejected' do

0 commit comments

Comments
 (0)