Class: Concurrent::Edge::Future

Inherits:
Event
  • Object
show all
Defined in:
lib/concurrent/edge/future.rb

Overview

Represents a value which will become available in future. May fail with a reason instead.

Direct Known Subclasses

CompletableFuture

Instance Method Summary collapse

Methods inherited from Event

#chain, #completed?, #default_executor, #initialize, #inspect, #on_completion, #on_completion!, #pending?, #set, #to_s, #unscheduled?, #wait

Constructor Details

This class inherits a constructor from Concurrent::Edge::Event

Instance Method Details

#any(*futures) ⇒ Future Also known as: |

Returns which has first completed value from futures.

Returns:

  • (Future)

    which has first completed value from futures



662
663
664
# File 'lib/concurrent/edge/future.rb', line 662

def any(*futures)
  AnyPromise.new([self, *futures], @DefaultExecutor).future
end

#chain_completable(completable_future) ⇒ Object Also known as: tangle



642
643
644
# File 'lib/concurrent/edge/future.rb', line 642

def chain_completable(completable_future)
  on_completion! { completable_future.complete_with internal_state }
end

#delayFuture

Inserts delay into the chain of Futures making rest of it lazy evaluated.

Returns:



668
669
670
# File 'lib/concurrent/edge/future.rb', line 668

def delay
  ZipFutureEventPromise.new(self, Delay.new(@DefaultExecutor).future, @DefaultExecutor).future
end

#exception(*args) ⇒ Object

Examples:

allows failed Future to be risen

raise Concurrent.future.fail


619
620
621
622
623
624
625
626
627
628
# File 'lib/concurrent/edge/future.rb', line 619

def exception(*args)
  raise 'obligation is not failed' unless failed?
  reason = internal_state.reason
  if reason.is_a?(::Array)
    reason.each { |e| log ERROR, 'Edge::Future', e }
    Concurrent::Error.new 'multiple exceptions, inspect log'
  else
    reason.exception(*args)
  end
end

#failed?(state = internal_state) ⇒ Boolean

Has Future been failed?

Returns:

  • (Boolean)


560
561
562
# File 'lib/concurrent/edge/future.rb', line 560

def failed?(state = internal_state)
  state.completed? && !state.success?
end

#flat(level = 1) ⇒ Object

zips with the Future in the value

Examples:

Concurrent.future { Concurrent.future { 1 } }.flat.vale # => 1


657
658
659
# File 'lib/concurrent/edge/future.rb', line 657

def flat(level = 1)
  FlatPromise.new(self, level, @DefaultExecutor).future
end

#fulfilled?Boolean

Returns:

  • (Boolean)


553
554
555
556
# File 'lib/concurrent/edge/future.rb', line 553

def fulfilled?
  deprecated_method 'fulfilled?', 'success?'
  success?
end

#on_failure(executor = nil) {|reason| ... } ⇒ Object

Returns self.

Yields:

  • (reason)

    executed async on ‘executor` when failed?

Returns:

  • self



722
723
724
# File 'lib/concurrent/edge/future.rb', line 722

def on_failure(executor = nil, &callback)
  add_callback :pr_async_callback_on_failure, executor || @DefaultExecutor, callback
end

#on_failure! {|reason| ... } ⇒ Object

Returns self.

Yields:

  • (reason)

    executed sync when failed?

Returns:

  • self



734
735
736
# File 'lib/concurrent/edge/future.rb', line 734

def on_failure!(&callback)
  add_callback :pr_callback_on_failure, callback
end

#on_success(executor = nil) {|value| ... } ⇒ Object

Returns self.

Yields:

  • (value)

    executed async on ‘executor` when success

Returns:

  • self



716
717
718
# File 'lib/concurrent/edge/future.rb', line 716

def on_success(executor = nil, &callback)
  add_callback :pr_async_callback_on_success, executor || @DefaultExecutor, callback
end

#on_success! {|value| ... } ⇒ Object

Returns self.

Yields:

  • (value)

    executed sync when success

Returns:

  • self



728
729
730
# File 'lib/concurrent/edge/future.rb', line 728

def on_success!(&callback)
  add_callback :pr_callback_on_success, callback
end

#reason(timeout = nil) ⇒ Exception?

Note:

If the Future can have value ‘nil` then it cannot be distinquished from `nil` returned on timeout. In this case is better to use first `wait` then `value` (or similar).

Note:

a thread should wait only once! For repeated checking use faster ‘completed?` check. If thread waits periodically it will dangerously grow the waiters stack.

Returns the reason of the Future’s failure.

Returns:

  • (Exception, nil)

    the reason of the Future’s failure



582
583
584
585
# File 'lib/concurrent/edge/future.rb', line 582

def reason(timeout = nil)
  touch
  internal_state.reason if wait_until_complete timeout
end

#rejected?Boolean

Returns:

  • (Boolean)


564
565
566
567
# File 'lib/concurrent/edge/future.rb', line 564

def rejected?
  deprecated_method 'rejected?', 'failed?'
  failed?
end

#rescue(executor = nil) {|reason| ... } ⇒ Future

Yields:

  • (reason)

    executed only on parent failure

Returns:



650
651
652
# File 'lib/concurrent/edge/future.rb', line 650

def rescue(executor = nil, &callback)
  RescuePromise.new(self, @DefaultExecutor, executor || @DefaultExecutor, &callback).future
end

#result(timeout = nil) ⇒ Array(Boolean, Object, Exception)?

Note:

If the Future can have value ‘nil` then it cannot be distinquished from `nil` returned on timeout. In this case is better to use first `wait` then `value` (or similar).

Note:

a thread should wait only once! For repeated checking use faster ‘completed?` check. If thread waits periodically it will dangerously grow the waiters stack.

Returns triplet of success, value, reason.

Returns:

  • (Array(Boolean, Object, Exception), nil)

    triplet of success, value, reason



590
591
592
593
# File 'lib/concurrent/edge/future.rb', line 590

def result(timeout = nil)
  touch
  internal_state.result if wait_until_complete timeout
end

#schedule(intended_time) ⇒ Future

Schedules rest of the chain for execution with specified time or on specified time

Returns:



674
675
676
677
678
679
680
# File 'lib/concurrent/edge/future.rb', line 674

def schedule(intended_time)
  chain do
    ZipFutureEventPromise.new(self,
                              ScheduledPromise.new(@DefaultExecutor, intended_time).event,
                              @DefaultExecutor).future
  end.flat
end

#state:pending, ...

Returns:

  • (:pending, :success, :failed)


# File 'lib/concurrent/edge/future.rb', line 544

#success?(state = internal_state) ⇒ Boolean

Has Future been success?

Returns:

  • (Boolean)


549
550
551
# File 'lib/concurrent/edge/future.rb', line 549

def success?(state = internal_state)
  state.completed? && state.success?
end

#then(executor = nil) {|value| ... } ⇒ Future

Yields:

  • (value)

    executed only on parent success

Returns:



632
633
634
# File 'lib/concurrent/edge/future.rb', line 632

def then(executor = nil, &callback)
  ThenPromise.new(self, @DefaultExecutor, executor || @DefaultExecutor, &callback).future
end

#then_ask(actor) ⇒ Future

Asks the actor with its value.

Returns:

  • (Future)

    new future with the response form the actor



638
639
640
# File 'lib/concurrent/edge/future.rb', line 638

def then_ask(actor)
  self.then { |v| actor.ask(v) }.flat
end

#then_put(channel) ⇒ Object

Note:

may block

Note:

only proof of concept



710
711
712
# File 'lib/concurrent/edge/future.rb', line 710

def then_put(channel)
  on_success(:io) { |value| channel.put value }
end

#then_select(*channels) ⇒ Future

Zips with selected value form the suplied channels

Returns:



684
685
686
# File 'lib/concurrent/edge/future.rb', line 684

def then_select(*channels)
  ZipFuturesPromise.new([self, Concurrent.select(*channels)], @DefaultExecutor).future
end

#value(timeout = nil) ⇒ Object?

Note:

If the Future can have value ‘nil` then it cannot be distinquished from `nil` returned on timeout. In this case is better to use first `wait` then `value` (or similar).

Note:

a thread should wait only once! For repeated checking use faster ‘completed?` check. If thread waits periodically it will dangerously grow the waiters stack.

Returns the value of the Future when success, nil on timeout.

Returns:

  • (Object, nil)

    the value of the Future when success, nil on timeout



574
575
576
577
# File 'lib/concurrent/edge/future.rb', line 574

def value(timeout = nil)
  touch
  internal_state.value if wait_until_complete timeout
end

#value!(timeout = nil) ⇒ Object?

Note:

If the Future can have value ‘nil` then it cannot be distinquished from `nil` returned on timeout. In this case is better to use first `wait` then `value` (or similar).

Note:

a thread should wait only once! For repeated checking use faster ‘completed?` check. If thread waits periodically it will dangerously grow the waiters stack.

Wait until Future is #complete?

Parameters:

  • timeout (Numeric) (defaults to: nil)

    the maximum time in second to wait.

Returns:

  • (Object, nil)

Raises:

  • reason on failure



612
613
614
615
# File 'lib/concurrent/edge/future.rb', line 612

def value!(timeout = nil)
  touch
  internal_state.value if wait_until_complete! timeout
end

#wait!(timeout = nil) ⇒ Event, ...

Note:

a thread should wait only once! For repeated checking use faster ‘completed?` check. If thread waits periodically it will dangerously grow the waiters stack.

Wait until Future is #complete?

Parameters:

  • timeout (Numeric) (defaults to: nil)

    the maximum time in second to wait.

Returns:

  • (Event, true, false)

    self or true/false if timeout is used

Raises:

  • reason on failure



600
601
602
603
604
# File 'lib/concurrent/edge/future.rb', line 600

def wait!(timeout = nil)
  touch
  result = wait_until_complete!(timeout)
  timeout ? result : self
end

#with_default_executor(executor) ⇒ Future

Changes default executor for rest of the chain

Returns:



690
691
692
# File 'lib/concurrent/edge/future.rb', line 690

def with_default_executor(executor)
  FutureWrapperPromise.new(self, executor).future
end

#zip(other) ⇒ Future Also known as: &

Zip with future producing new Future

Returns:



696
697
698
699
700
701
702
# File 'lib/concurrent/edge/future.rb', line 696

def zip(other)
  if other.is_a?(Future)
    ZipFutureFuturePromise.new(self, other, @DefaultExecutor).future
  else
    ZipFutureEventPromise.new(self, other, @DefaultExecutor).future
  end
end