Class: Cql::Future
- Inherits:
-
Object
- Object
- Cql::Future
- Defined in:
- lib/cql/future.rb
Overview
A future represents the value of a process that may not yet have completed.
Direct Known Subclasses
Class Method Summary collapse
-
.combine(*futures) ⇒ Future<Array>
Combine multiple futures into a new future which completes when all constituent futures complete, or fail when one or more of them fails.
-
.completed(value = nil) ⇒ Future
Creates a new future which is completed.
-
.failed(error) ⇒ Future
Creates a new future which is failed.
Instance Method Summary collapse
-
#complete!(v = nil) ⇒ Object
Completes the future.
-
#complete? ⇒ Boolean
Returns whether or not the future is complete.
-
#fail!(error) ⇒ Object
Fails the future.
-
#failed? ⇒ Boolean
Returns whether or not the future is failed.
-
#flat_map {|value| ... } ⇒ Future
Returns a new future representing a transformation of this future’s value, but where the transformation itself may be asynchronous.
-
#initialize ⇒ Future
constructor
A new instance of Future.
-
#map {|value| ... } ⇒ Future
Returns a new future representing a transformation of this future’s value.
-
#on_complete {|value| ... } ⇒ Object
Registers a listener for when this future completes.
-
#on_failure {|error| ... } ⇒ Object
Registers a listener for when this future fails.
-
#value ⇒ Object
(also: #get)
Returns the value of this future, blocking until it is available, if necessary.
Constructor Details
#initialize ⇒ Future
Returns a new instance of Future.
12 13 14 15 16 17 |
# File 'lib/cql/future.rb', line 12 def initialize @complete_listeners = [] @failure_listeners = [] @value_barrier = Queue.new @state_lock = Mutex.new end |
Class Method Details
.combine(*futures) ⇒ Future<Array>
Combine multiple futures into a new future which completes when all constituent futures complete, or fail when one or more of them fails.
The value of the combined future is an array of the values of the constituent futures.
28 29 30 31 32 33 34 |
# File 'lib/cql/future.rb', line 28 def self.combine(*futures) if futures.any? CombinedFuture.new(*futures) else completed([]) end end |
.completed(value = nil) ⇒ Future
Creates a new future which is completed.
41 42 43 |
# File 'lib/cql/future.rb', line 41 def self.completed(value=nil) CompletedFuture.new(value) end |
.failed(error) ⇒ Future
Creates a new future which is failed.
50 51 52 |
# File 'lib/cql/future.rb', line 50 def self.failed(error) FailedFuture.new(error) end |
Instance Method Details
#complete!(v = nil) ⇒ Object
Completes the future.
This will trigger all completion listeners in the calling thread.
60 61 62 63 64 65 66 67 68 69 70 71 72 |
# File 'lib/cql/future.rb', line 60 def complete!(v=nil) @state_lock.synchronize do raise FutureError, 'Future already completed' if complete? || failed? @value = v @complete_listeners.each do |listener| listener.call(@value) end end ensure @state_lock.synchronize do @value_barrier << :ping end end |
#complete? ⇒ Boolean
Returns whether or not the future is complete
76 77 78 |
# File 'lib/cql/future.rb', line 76 def complete? defined? @value end |
#fail!(error) ⇒ Object
Fails the future.
This will trigger all failure listeners in the calling thread.
115 116 117 118 119 120 121 122 123 124 125 126 127 |
# File 'lib/cql/future.rb', line 115 def fail!(error) @state_lock.synchronize do raise FutureError, 'Future already completed' if failed? || complete? @error = error @failure_listeners.each do |listener| listener.call(error) end end ensure @state_lock.synchronize do @value_barrier << :ping end end |
#failed? ⇒ Boolean
Returns whether or not the future is failed.
131 132 133 |
# File 'lib/cql/future.rb', line 131 def failed? !!@error end |
#flat_map {|value| ... } ⇒ Future
Returns a new future representing a transformation of this future’s value, but where the transformation itself may be asynchronous.
This method is useful when you want to chain asynchronous operations.
184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 |
# File 'lib/cql/future.rb', line 184 def flat_map(&block) fp = Future.new on_failure { |e| fp.fail!(e) } on_complete do |v| begin fpp = block.call(v) fpp.on_failure { |e| fp.fail!(e) } fpp.on_complete do |vv| fp.complete!(vv) end rescue => e fp.fail!(e) end end fp end |
#map {|value| ... } ⇒ Future
Returns a new future representing a transformation of this future’s value.
158 159 160 161 162 163 164 165 166 167 168 169 170 |
# File 'lib/cql/future.rb', line 158 def map(&block) fp = Future.new on_failure { |e| fp.fail!(e) } on_complete do |v| begin vv = block.call(v) fp.complete!(vv) rescue => e fp.fail!(e) end end fp end |
#on_complete {|value| ... } ⇒ Object
Registers a listener for when this future completes
84 85 86 87 88 89 90 91 92 |
# File 'lib/cql/future.rb', line 84 def on_complete(&listener) @state_lock.synchronize do if complete? listener.call(value) else @complete_listeners << listener end end end |
#on_failure {|error| ... } ⇒ Object
Registers a listener for when this future fails
139 140 141 142 143 144 145 146 147 |
# File 'lib/cql/future.rb', line 139 def on_failure(&listener) @state_lock.synchronize do if failed? listener.call(@error) else @failure_listeners << listener end end end |
#value ⇒ Object Also known as: get
Returns the value of this future, blocking until it is available, if necessary.
If the future fails this method will raise the error that failed the future.
100 101 102 103 104 105 106 |
# File 'lib/cql/future.rb', line 100 def value raise @error if @error return @value if defined? @value @value_barrier.pop raise @error if @error return @value end |