@@ -121,6 +121,7 @@ def post_on(executor, *args, &job)
121121 class Event < Synchronization ::Object
122122 include Concern ::Deprecation
123123
124+ # @!visibility private
124125 class State
125126 def completed?
126127 raise NotImplementedError
@@ -131,6 +132,7 @@ def to_sym
131132 end
132133 end
133134
135+ # @!visibility private
134136 class Pending < State
135137 def completed?
136138 false
@@ -141,6 +143,7 @@ def to_sym
141143 end
142144 end
143145
146+ # @!visibility private
144147 class Completed < State
145148 def completed?
146149 true
@@ -151,7 +154,9 @@ def to_sym
151154 end
152155 end
153156
157+ # @!visibility private
154158 PENDING = Pending . new
159+ # @!visibility private
155160 COMPLETED = Completed . new
156161
157162 def initialize ( promise , default_executor )
@@ -192,11 +197,14 @@ def completed?(state = @State.get)
192197
193198 # Wait until Event is #complete?
194199 # @param [Numeric] timeout the maximum time in second to wait.
195- # @return [Event] self
200+ # @return [Event, true, false] self or true/false if timeout is used
201+ # @!macro [attach] edge.periodical_wait
202+ # @note a thread should wait only once! For repeated checking use faster `completed?` check.
203+ # If thread waits periodically it will dangerously grow the waiters stack.
196204 def wait ( timeout = nil )
197205 touch
198- wait_until_complete timeout
199- self
206+ result = wait_until_complete ( timeout )
207+ timeout ? result : self
200208 end
201209
202210 # @!visibility private
@@ -335,20 +343,19 @@ def waiting_threads
335343
336344 private
337345
346+ # @return [true, false]
338347 def wait_until_complete ( timeout )
339348 while true
340349 last_waiter = @Waiters . peek # waiters' state before completion
341- break if completed?
350+ return true if completed?
342351
343352 # synchronize so it cannot be signaled before it waits
344353 synchronize do
345354 # ok only if completing thread did not start signaling
346355 next unless @Waiters . compare_and_push last_waiter , Thread . current
347- ns_wait_until ( timeout ) { completed? }
356+ return ns_wait_until ( timeout ) { completed? }
348357 end
349- break
350358 end
351- self
352359 end
353360
354361 def complete_state
@@ -386,6 +393,7 @@ def call_callbacks
386393
387394 # Represents a value which will become available in future. May fail with a reason instead.
388395 class Future < Event
396+ # @!visibility private
389397 class CompletedWithResult < Completed
390398 def result
391399 [ success? , value , reason ]
@@ -404,6 +412,7 @@ def reason
404412 end
405413 end
406414
415+ # @!visibility private
407416 class Success < CompletedWithResult
408417 def initialize ( value )
409418 @Value = value
@@ -430,12 +439,14 @@ def to_sym
430439 end
431440 end
432441
442+ # @!visibility private
433443 class SuccessArray < Success
434444 def apply ( block )
435445 block . call *value
436446 end
437447 end
438448
449+ # @!visibility private
439450 class Failed < CompletedWithResult
440451 def initialize ( reason )
441452 @Reason = reason
@@ -468,7 +479,7 @@ def apply(block)
468479 # Has Future been success?
469480 # @return [Boolean]
470481 def success? ( state = @State . get )
471- state . success?
482+ state . completed? && state . success?
472483 end
473484
474485 def fulfilled?
@@ -479,52 +490,60 @@ def fulfilled?
479490 # Has Future been failed?
480491 # @return [Boolean]
481492 def failed? ( state = @State . get )
482- ! success? ( state )
493+ state . completed? && ! state . success?
483494 end
484495
485496 def rejected?
486497 deprecated_method 'rejected?' , 'failed?'
487498 failed?
488499 end
489500
490- # @return [Object] the value of the Future when success
501+ # @return [Object, nil] the value of the Future when success, nil on timeout
502+ # @!macro [attach] edge.timeout_nil
503+ # @note If the Future can have value `nil` then it cannot be distinquished from `nil` returned on timeout.
504+ # In this case is better to use first `wait` then `value` (or similar).
505+ # @!macro edge.periodical_wait
491506 def value ( timeout = nil )
492507 touch
493- wait_until_complete timeout
494- @State . get . value
508+ @State . get . value if wait_until_complete timeout
495509 end
496510
497- # @return [Exception] the reason of the Future's failure
511+ # @return [Exception, nil] the reason of the Future's failure
512+ # @!macro edge.timeout_nil
513+ # @!macro edge.periodical_wait
498514 def reason ( timeout = nil )
499515 touch
500- wait_until_complete timeout
501- @State . get . reason
516+ @State . get . reason if wait_until_complete timeout
502517 end
503518
504- # @return [Array(Boolean, Object, Exception)] triplet of success, value, reason
519+ # @return [Array(Boolean, Object, Exception), nil] triplet of success, value, reason
520+ # @!macro edge.timeout_nil
521+ # @!macro edge.periodical_wait
505522 def result ( timeout = nil )
506523 touch
507- wait_until_complete timeout
508- @State . get . result
524+ @State . get . result if wait_until_complete timeout
509525 end
510526
511527 # Wait until Future is #complete?
512528 # @param [Numeric] timeout the maximum time in second to wait.
513529 # @raise reason on failure
514- # @return [Event] self
530+ # @return [Event, true, false] self or true/false if timeout is used
531+ # @!macro edge.periodical_wait
515532 def wait! ( timeout = nil )
516533 touch
517- wait_until_complete! timeout
534+ result = wait_until_complete! ( timeout )
535+ timeout ? result : self
518536 end
519537
520538 # Wait until Future is #complete?
521539 # @param [Numeric] timeout the maximum time in second to wait.
522540 # @raise reason on failure
523- # @return [Object]
541+ # @return [Object, nil]
542+ # @!macro edge.timeout_nil
543+ # @!macro edge.periodical_wait
524544 def value! ( timeout = nil )
525545 touch
526- wait_until_complete! ( timeout )
527- @State . get . value
546+ @State . get . value if wait_until_complete! timeout
528547 end
529548
530549 # @example allows failed Future to be risen
@@ -631,9 +650,9 @@ def apply(block)
631650 private
632651
633652 def wait_until_complete! ( timeout = nil )
634- wait_until_complete ( timeout )
653+ result = wait_until_complete ( timeout )
635654 raise self if failed?
636- self
655+ result
637656 end
638657
639658 def complete_state ( success , value , reason )
0 commit comments