Skip to content

Commit 53128c3

Browse files
committed
Fix any methods
- add missing Event#any - allow mix of futures and events, completed event has value nil and is always successful - any does not propagate touch if already complete
1 parent 76e956c commit 53128c3

File tree

1 file changed

+137
-135
lines changed

1 file changed

+137
-135
lines changed

lib/concurrent/promises.rb

Lines changed: 137 additions & 135 deletions
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ def any_event(*events)
145145
end
146146

147147
def any_event_on(default_executor, *events)
148-
AnyCompletedEventPromise.new(events, default_executor).event
148+
AnyCompleteEventPromise.new(events, default_executor).event
149149
end
150150

151151
# TODO consider adding first(count, *futures)
@@ -170,6 +170,8 @@ def to_sym
170170
end
171171
end
172172

173+
private_constant :State
174+
173175
class Pending < State
174176
def completed?
175177
false
@@ -180,22 +182,135 @@ def to_sym
180182
end
181183
end
182184

183-
class Completed < State
185+
private_constant :Pending
186+
187+
class CompletedWithResult < State
184188
def completed?
185189
true
186190
end
187191

188192
def to_sym
189193
:completed
190194
end
195+
196+
def result
197+
[success?, value, reason]
198+
end
199+
200+
def success?
201+
raise NotImplementedError
202+
end
203+
204+
def value
205+
raise NotImplementedError
206+
end
207+
208+
def reason
209+
raise NotImplementedError
210+
end
211+
212+
def apply
213+
raise NotImplementedError
214+
end
215+
end
216+
217+
private_constant :CompletedWithResult
218+
219+
# @!visibility private
220+
class Success < CompletedWithResult
221+
def initialize(value)
222+
@Value = value
223+
end
224+
225+
def success?
226+
true
227+
end
228+
229+
def apply(args, block)
230+
block.call value, *args
231+
end
232+
233+
def value
234+
@Value
235+
end
236+
237+
def reason
238+
nil
239+
end
240+
241+
def to_sym
242+
:success
243+
end
244+
end
245+
246+
# @!visibility private
247+
class SuccessArray < Success
248+
def apply(args, block)
249+
block.call(*value, *args)
250+
end
251+
end
252+
253+
# @!visibility private
254+
class Failed < CompletedWithResult
255+
def initialize(reason)
256+
@Reason = reason
257+
end
258+
259+
def success?
260+
false
261+
end
262+
263+
def value
264+
nil
265+
end
266+
267+
def reason
268+
@Reason
269+
end
270+
271+
def to_sym
272+
:failed
273+
end
274+
275+
def apply(args, block)
276+
block.call reason, *args
277+
end
278+
end
279+
280+
# @!visibility private
281+
class PartiallyFailed < CompletedWithResult
282+
def initialize(value, reason)
283+
super()
284+
@Value = value
285+
@Reason = reason
286+
end
287+
288+
def success?
289+
false
290+
end
291+
292+
def to_sym
293+
:failed
294+
end
295+
296+
def value
297+
@Value
298+
end
299+
300+
def reason
301+
@Reason
302+
end
303+
304+
def apply(args, block)
305+
block.call(*reason, *args)
306+
end
191307
end
192308

193-
private_constant :State, :Pending, :Completed
194309

195310
# @!visibility private
196311
PENDING = Pending.new
197312
# @!visibility private
198-
COMPLETED = Completed.new
313+
COMPLETED = Success.new(nil)
199314

200315
def initialize(promise, default_executor)
201316
super()
@@ -284,12 +399,18 @@ def zip(other)
284399
if other.is?(Future)
285400
ZipFutureEventPromise.new(other, self, @DefaultExecutor).future
286401
else
287-
ZipEventEventPromise.new(self, other, @DefaultExecutor).future
402+
ZipEventEventPromise.new(self, other, @DefaultExecutor).event
288403
end
289404
end
290405

291406
alias_method :&, :zip
292407

408+
def any(future)
409+
AnyCompleteEventPromise.new([self, future], @DefaultExecutor).event
410+
end
411+
412+
alias_method :|, :any
413+
293414
# Inserts delay into the chain of Futures making rest of it lazy evaluated.
294415
# @return [Event]
295416
def delay
@@ -447,119 +568,6 @@ def call_callbacks
447568

448569
# Represents a value which will become available in future. May fail with a reason instead.
449570
class Future < Event
450-
class CompletedWithResult < Completed
451-
def result
452-
[success?, value, reason]
453-
end
454-
455-
def success?
456-
raise NotImplementedError
457-
end
458-
459-
def value
460-
raise NotImplementedError
461-
end
462-
463-
def reason
464-
raise NotImplementedError
465-
end
466-
467-
def apply
468-
raise NotImplementedError
469-
end
470-
end
471-
472-
# @!visibility private
473-
class Success < CompletedWithResult
474-
def initialize(value)
475-
@Value = value
476-
end
477-
478-
def success?
479-
true
480-
end
481-
482-
def apply(args, block)
483-
block.call value, *args
484-
end
485-
486-
def value
487-
@Value
488-
end
489-
490-
def reason
491-
nil
492-
end
493-
494-
def to_sym
495-
:success
496-
end
497-
end
498-
499-
# @!visibility private
500-
class SuccessArray < Success
501-
def apply(args, block)
502-
block.call(*value, *args)
503-
end
504-
end
505-
506-
# @!visibility private
507-
class Failed < CompletedWithResult
508-
def initialize(reason)
509-
@Reason = reason
510-
end
511-
512-
def success?
513-
false
514-
end
515-
516-
def value
517-
nil
518-
end
519-
520-
def reason
521-
@Reason
522-
end
523-
524-
def to_sym
525-
:failed
526-
end
527-
528-
def apply(args, block)
529-
block.call reason, *args
530-
end
531-
end
532-
533-
# @!visibility private
534-
class PartiallyFailed < CompletedWithResult
535-
def initialize(value, reason)
536-
super()
537-
@Value = value
538-
@Reason = reason
539-
end
540-
541-
def success?
542-
false
543-
end
544-
545-
def to_sym
546-
:failed
547-
end
548-
549-
def value
550-
@Value
551-
end
552-
553-
def reason
554-
@Reason
555-
end
556-
557-
def apply(args, block)
558-
block.call(*reason, *args)
559-
end
560-
end
561-
562-
private_constant :CompletedWithResult
563571

564572
# @!method state
565573
# @return [:pending, :success, :failed]
@@ -671,8 +679,8 @@ def flat(level = 1)
671679
end
672680

673681
# @return [Future] which has first completed value from futures
674-
def any(*futures)
675-
AnyCompleteFuturePromise.new([self, *futures], @DefaultExecutor).future
682+
def any(future)
683+
AnyCompleteFuturePromise.new([self, future], @DefaultExecutor).future
676684
end
677685

678686
# Inserts delay into the chain of Futures making rest of it lazy evaluated.
@@ -1317,13 +1325,17 @@ def on_completable(done_future)
13171325
end
13181326
end
13191327

1320-
class AnyCompleteFuturePromise < BlockedPromise
1328+
class AbstractAnyPromise < BlockedPromise
1329+
def touch
1330+
blocked_by.each(&:touch) unless @Future.completed?
1331+
end
1332+
end
1333+
1334+
class AnyCompleteFuturePromise < AbstractAnyPromise
13211335

13221336
private
13231337

13241338
def initialize(blocked_by_futures, default_executor)
1325-
blocked_by_futures.all? { |f| f.is_a? Future } or
1326-
raise ArgumentError, 'accepts only Futures not Events'
13271339
super(Future.new(self, default_executor), blocked_by_futures, blocked_by_futures.size)
13281340
end
13291341

@@ -1336,7 +1348,7 @@ def on_completable(done_future)
13361348
end
13371349
end
13381350

1339-
class AnyCompleteEventPromise < BlockedPromise
1351+
class AnyCompleteEventPromise < AbstractAnyPromise
13401352

13411353
private
13421354

@@ -1353,23 +1365,13 @@ def on_completable(done_future)
13531365
end
13541366
end
13551367

1356-
class AnySuccessfulFuturePromise < BlockedPromise
1368+
class AnySuccessfulFuturePromise < AnyCompleteFuturePromise
13571369

13581370
private
13591371

1360-
def initialize(blocked_by_futures, default_executor)
1361-
blocked_by_futures.all? { |f| f.is_a? Future } or
1362-
raise ArgumentError, 'accepts only Futures not Events'
1363-
super(Future.new(self, default_executor), blocked_by_futures, blocked_by_futures.size)
1364-
end
1365-
13661372
def completable?(countdown, future)
13671373
future.success? || super(countdown, future)
13681374
end
1369-
1370-
def on_completable(done_future)
1371-
complete_with done_future.internal_state, false
1372-
end
13731375
end
13741376

13751377
class DelayPromise < InnerPromise

0 commit comments

Comments
 (0)