Register a FutureEventListener to be invoked when the computation completes.
Register a FutureEventListener to be invoked when the computation completes. This method is typically used by Java programs because it avoids the use of small Function objects.
this should be used for side-effects
transformedBy for a Java friendly way to produce
a new Future
from the result of a computation.
respond for a Scala API.
Become the other promise.
Become the other promise. become
declares an equivalence
relation: this
and other
are the same.
By becoming other
, its waitlists are now merged into this
's,
and this
becomes canonical. The same is true of interrupt
handlers: other
's interrupt handler is overwritten with the
handlers installed for this
.
Note: Using become
and setInterruptHandler
on the same
promise is not recommended. Consider the following, which
demonstrates unexpected behavior related to this usage.
val a, b = new Promise[Unit] a.setInterruptHandler { case _ => println("A") } b.become(a) b.setInterruptHandler { case _ => println("B") } a.raise(new Exception)
This prints "B", the action in the interrupt handler for b
,
which is unexpected because we raised on a
. In this case and
others, using com.twitter.util.Future.proxyTo may be more
appropriate.
Note that this
must be unsatisfied at the time of the call,
and not race with any other setters. become
is a form of
satisfying the promise.
This has the combined effect of compressing the other
into
this
, effectively providing a form of tail-call elimination
when used in recursion constructs. transform
(and thus any
other combinator) use this to compress Futures, freeing them
from space leaks when used with recursive constructions.
Note: do not use become with cyclic graphs of futures: the
behavior of racing a.become(b)
with b.become(a)
is undefined
(where a
and b
may resolve as such transitively).
Sequentially compose this
with f
.
Returns a new Future that fails if it is not satisfied before the given time.
Returns a new Future that fails if it is not satisfied before the given time.
Note: On timeout, the underlying future is not interrupted.
Note: Interrupting a returned future would not prevent it from being satisfied with a given exception (when the time comes).
to run timeout on.
indicates when to stop waiting for the result to be available.
exception to throw.
Returns a new Future that fails if it is not satisfied before the given time.
Returns a new Future that fails if it is not satisfied before the given time.
Note: On timeout, the underlying future is not interrupted.
Returns a new Future that fails if it is not satisfied before the given time.
Returns a new Future that fails if it is not satisfied before the given time.
Same as the other by
, but with an implicit timer. Sometimes this is more convenient.
Note: On timeout, the underlying future is not interrupted.
Should only be called when this Promise has already been fulfilled
or it is becoming another Future via become
.
Should only be called when this Promise has already been fulfilled
or it is becoming another Future via become
.
Delay the completion of this Future for at least howlong
from now.
Delay the completion of this Future for at least howlong
from now.
Note: Interrupting a returned future would not prevent it from becoming this future (when the time comes).
Invoked regardless of whether the computation completed successfully or unsuccessfully.
Invoked regardless of whether the computation completed successfully or unsuccessfully. Implemented in terms of respond so that subclasses control evaluation order. Returns a chained Future.
The returned Future
will be satisfied when this,
the original future, is done.
the side-effect to apply when the computation completes.
import com.twitter.util.Future def callbacks(result: Future[Int]): Future[Int] = result.onSuccess { i => println(i) }.onFailure { e => println(e.getMessage) }.ensure { println("always printed") }
val a = Future.value(1) callbacks(a) // prints "1" and then "always printed"
this should be used for side-effects.
respond if you need the result of the computation for usage in the side-effect.
If this, the original future, succeeds, run f
on the result.
If this, the original future, succeeds, run f
on the result.
The returned result is a Future that is satisfied when the original future
and the callback, f
, are done.
import com.twitter.util.{Await, Future} val f: Future[Int] = Future.exception(new Exception("boom!")) val newf: Future[Int] = f.flatMap { x => println("I'm being executed") // won't print Future.value(x + 10) } Await.result(newf) // throws java.lang.Exception: boom!
import com.twitter.util.{Await, Future} val f: Future[Int] = Future.value(1) val newf: Future[Int] = f.flatMap { x => Future.value(x + 10) } Await.result(newf) // 11 // Await.result blocks the current thread, // don't use it except for tests.
If the original future fails, this one will also fail, without executing f
and preserving the failed computation of this
Converts a Future[Future[B]]
into a Future[B]
.
Converts a Future[Future[B]]
into a Future[B]
.
Invoke the callback only if the Future returns successfully.
Forward interrupts to another future.
Forward interrupts to another future. If the other future is fulfilled, this is a no-op. Calling this multiple times is not recommended as the resulting state may not be as expected.
the Future to which interrupts are forwarded.
If this, the original future, results in an exceptional computation,
rescueException
may convert the failure into a new result.
If this, the original future, results in an exceptional computation,
rescueException
may convert the failure into a new result.
The returned result is a Future
that is satisfied when the original
future and the callback, rescueException
, are done.
This is the equivalent of map for failed computations.
import com.twitter.util.{Await, Future} val f1: Future[Int] = Future.exception(new Exception("boom1!")) val f2: Future[Int] = Future.exception(new Exception("boom2!")) val newf: Future[Int] => Future[Int] = x => x.handle { case e: Exception if e.getMessage == "boom1!" => 1 } Await.result(newf(f1)) // 1 Await.result(newf(f2)) // throws java.lang.Exception: boom2! // Await.result blocks the current thread, // don't use it except for tests.
Makes a derivative Future
which will be satisfied with the result
of the parent.
Makes a derivative Future
which will be satisfied with the result
of the parent. However, if it's interrupted, it will detach from
the parent Future
, satisfy itself with the exception raised to
it, and won't propagate the interruption back to the parent
Future
.
This is useful for when a Future
is shared between many contexts,
where it may not be useful to discard the underlying computation
if just one context is no longer interested in the result. In
particular, this is different from Future.masked in that it will
prevent memory leaks if the parent Future will never be
satisfied, because closures that are attached to this derivative
Future
will not be held onto by the killer Future
.
Is the result of the Future available yet?
Checks whether a Unit-typed Future is done.
Checks whether a Unit-typed Future is done. By convention, futures of type Future[Unit] are used for signalling.
Returns this promise's interrupt if it is interrupted.
Is this Awaitable ready? In other words: would calling Awaitable.ready block?
Is this Awaitable ready? In other words: would calling Awaitable.ready block?
Joins this future with a given other
future into a Future[(A, B)]
(future of a Tuple2
).
Joins this future with a given other
future into a Future[(A, B)]
(future of a Tuple2
). If this or other
future fails, the returned Future
is immediately satisfied by that failure.
Joins this future with a given other
future and applies fn
to its result.
Joins this future with a given other
future and applies fn
to its result.
If this or other
future fails, the returned Future
is immediately satisfied
by that failure.
Before (using join):
val ab = a.join(b).map { case (a, b) => Foo(a, b) }
After (using joinWith):
val ab = a.joinWith(b)(Foo.apply)
Returns the result of the computation as a Future[Try[A]]
.
Returns the result of the computation as a Future[Try[A]]
.
import com.twitter.util.{Await, Future, Try} val fr: Future[Int] = Future.value(1) val ft: Future[Int] = Future.exception(new Exception("boom!")) val r: Future[Try[Int]] = fr.liftToTry val t: Future[Try[Int]] = ft.liftToTry Await.result(r) // Return(1) Await.result(t) // Throw(java.lang.Exception: boom!) // Await.result blocks the current thread, // don't use it except for tests.
Lowers a Future[Try[T]]
into a Future[T]
.
Lowers a Future[Try[T]]
into a Future[T]
.
import com.twitter.util.{Await, Future, Return, Throw, Try} val fr: Future[Try[Int]] = Future.value(Return(1)) val ft: Future[Try[Int]] = Future.value(Throw(new Exception("boom!"))) val r: Future[Int] = fr.lowerFromTry val t: Future[Int] = ft.lowerFromTry Await.result(r) // 1 Await.result(t) // throws java.lang.Exception: boom! // Await.result blocks the current thread, // don't use it except for tests.
If this, the original future, succeeds, run f
on the result.
If this, the original future, succeeds, run f
on the result.
The returned result is a Future that is satisfied when the original future
and the callback, f
, are done.
import com.twitter.util.{Await, Future} val f: Future[Int] = Future.exception(new Exception("boom!")) val newf: Future[Int] = f.map { x => println("I'm being executed") // won't print x + 10 } Await.result(newf) // throws java.lang.Exception: boom!
import com.twitter.util.{Await, Future} val f: Future[Int] = Future.value(1) val newf: Future[Int] = f.map { x => x + 10 } Await.result(newf) // 11 // Await.result blocks the current thread, // don't use it except for tests.
If the original future fails, this one will also fail, without executing f
and preserving the failed computation of this
onSuccess for side-effecting chained computations.
flatMap for computations that return Future
s.
Returns an identical Future
except that it ignores interrupts which match a predicate.
Returns an identical Future
except that it ignores interrupts which match a predicate.
This means that a Promise's interrupt handler
will not execute on calls to Future.raise for inputs to pred
that evaluate to true
. Also, raise
will not be forwarded to chained Futures.
For example:
val p = new Promise[Int]() p.setInterruptHandler { case x => println(s"interrupt handler for ${x.getClass}") } val f1: Future[Int] = p.mask { case _: IllegalArgumentException => true } f1.raise(new IllegalArgumentException("ignored!")) // nothing will be printed f1.map(_ + 1).raise(new IllegalArgumentException("ignored!")) // nothing will be printed val f2: Future[Int] = p.mask { case _: IllegalArgumentException => true } f2.raise(new Exception("fire!")) // will print "interrupt handler for class java.lang.Exception"
Returns an identical Future
that ignores all interrupts.
Returns an identical Future
that ignores all interrupts.
This means that a Promise's interrupt handler
will not execute for any call to Future.raise. Also, raise
will not
be forwarded to chained Futures.
For example:
import com.twitter.util.{Future, Promise} val p = new Promise[Int]() p.setInterruptHandler { case _ => println("interrupt handler") } val f: Future[Int] = p.masked f.raise(new Exception("ignored!")) // nothing will be printed f1.map(_ + 1).raise(new Exception("ignored!")) // nothing will be printed
Invoke the function on the error, if the computation was unsuccessful.
Invoke the function on the error, if the computation was
unsuccessful. Returns a chained Future as in respond
.
chained Future
import com.twitter.util.Future def callbacks(result: Future[Int]): Future[Int] = result.onSuccess { i => println(i) }.onFailure { e => println(e.getMessage) }.ensure { println("always printed") }
val b = Future.exception(new Exception("boom!")) callbacks(b) // prints "boom!" and then "always printed"
if fn
is a PartialFunction
and the input is not defined for a given
Throwable, the resulting MatchError
will propagate to the current
Monitor
. This will happen if you use a construct such as
future.onFailure { case NonFatal(e) => ... }
when the Throwable
is "fatal".
this should be used for side-effects.
handle and rescue to produce a new Future
from the result of
the computation.
Invoke the function on the result, if the computation was successful.
Invoke the function on the result, if the computation was
successful. Returns a chained Future as in respond
.
chained Future
import com.twitter.util.Future def callbacks(result: Future[Int]): Future[Int] = result.onSuccess { i => println(i) }.onFailure { e => println(e.getMessage) }.ensure { println("always printed") }
val a = Future.value(1) callbacks(a) // prints "1" and then "always printed"
this should be used for side-effects.
flatMap and map to produce a new Future
from the result of
the computation.
A synonym for select: Choose the first Future
to be satisfied.
Polls for an available result.
Send updates from this Future to the other.
Send updates from this Future to the other.
other
must not yet be satisfied at the time of the call.
After this call, nobody else should satisfy other
.
using proxyTo
will mask interrupts to this future, and it's
the user's responsibility to set an interrupt handler on other
to raise on f. In some cases, using
com.twitter.util.Promise.become may be more appropriate.
Raise the given throwable as an interrupt.
Raise the given throwable as an interrupt. Interrupts are
one-shot and latest-interrupt wins. That is, the last interrupt
to have been raised is delivered exactly once to the Promise
responsible for making progress on the future (multiple such
promises may be involved in flatMap
chains).
Raising an interrupt does not alter the externally observable
state of the Future
. They are used to signal to the producer
of the future's value that the result is no longer desired (for
whatever reason given in the passed Throwable
). For example:
import com.twitter.util.Promise val p = new Promise[Unit]() p.setInterruptHandler { case _ => println("interrupt handler fired") } p.poll // is `None` p.raise(new Exception("raised!")) p.poll // is still `None`
In the context of a Future
created via composition (e.g.
flatMap
/onSuccess
/transform
), raise
-ing on that Future
will
call raise
on the head of the chain which created this Future
.
For example:
import com.twitter.util.Promise val p = new Promise[Int]() p.setInterruptHandler { case _ => println("interrupt handler fired") } val f = p.map(_ + 1) f.raise(new Exception("fire!"))
The call to f.raise
will call p.raise
and print "interrupt handler fired".
When the head of that chain of Futures
is satisfied, the next
Future
in the chain created by composition will have raise
called. For example:
import com.twitter.util.Promise val p1, p2 = new Promise[Int]() p1.setInterruptHandler { case _ => println("p1 interrupt handler") } p2.setInterruptHandler { case _ => println("p2 interrupt handler") } val f = p1.flatMap { _ => p2 } f.raise(new Exception("fire!")) // will print "p1 interrupt handler" p1.setValue(1) // will print "p2 interrupt handler"
Returns a new Future that fails if this Future does not return in time.
Returns a new Future that fails if this Future does not return in time.
Note: On timeout, the underlying future is interrupted.
Returns a new Future that fails if this Future does not return in time.
Returns a new Future that fails if this Future does not return in time.
Same as the other raiseWithin
, but with an implicit timer. Sometimes this is more convenient.
Note: On timeout, the underlying future is interrupted.
Returns a new Future that fails if this Future does not return in time.
Returns a new Future that fails if this Future does not return in time.
Same as the other raiseWithin
, but with an implicit timer. Sometimes this is more convenient.
Note: On timeout, the underlying future is interrupted.
Support for Await.ready
.
If this, the original future, results in an exceptional computation,
rescueException
may convert the failure into a new result.
If this, the original future, results in an exceptional computation,
rescueException
may convert the failure into a new result.
The returned result is a Future
that is satisfied when the original
future and the callback, rescueException
, are done.
This is the equivalent of flatMap for failed computations.
import com.twitter.util.{Await, Future} val f1: Future[Int] = Future.exception(new Exception("boom1!")) val f2: Future[Int] = Future.exception(new Exception("boom2!")) val newf: Future[Int] => Future[Int] = x => x.rescue { case e: Exception if e.getMessage == "boom1!" => Future.value(1) } Await.result(newf(f1)) // 1 Await.result(newf(f2)) // throws java.lang.Exception: boom2! // Await.result blocks the current thread, // don't use it except for tests.
Note: exceptions in responds are monitored.
Support for Await.result
.
Choose the first Future to be satisfied.
Choose the first Future to be satisfied.
another Future
a new Future whose result is that of the first of this and other to return
Sets a Unit-typed future.
Sets a Unit-typed future. By convention, futures of type Future[Unit] are used for signalling.
Populate the Promise with the given exception.
Populate the Promise with the given exception.
ImmutableResult
if the Promise is already populated
(Re)sets the interrupt handler.
(Re)sets the interrupt handler. There is only one active interrupt handler.
the new interrupt handler
Populate the Promise with the given result.
Populate the Promise with the given result.
ImmutableResult
if the Promise is already populated
Convert a Twitter Future to a Java native CompletableFuture.
Convert a Twitter Future to a Java native CompletableFuture. This should match the semantics of a Java Future as closely as possible to avoid issues with the way another API might use them. At the same time, its semantics should be similar to those of a Twitter Future, so it propagates cancellation. See:
https://download.oracle.com/javase/6/docs/api/java/util/concurrent/Future.html#cancel(boolean)
Convert a Twitter Future to a Java native Future.
Convert a Twitter Future to a Java native Future. This should match the semantics of a Java Future as closely as possible to avoid issues with the way another API might use them. At the same time, its semantics should be similar to those of a Twitter Future, so it propagates cancellation. See:
https://download.oracle.com/javase/6/docs/api/java/util/concurrent/Future.html#cancel(boolean)
An Offer for this future.
Transform the Future[A]
into a Future[B]
using the
FutureTransformer.
Transform the Future[A]
into a Future[B]
using the
FutureTransformer. The FutureTransformer handles both success
(Return) and failure (Throw) values by implementing map
/flatMap
and handle
/rescue
. This method is typically used by Java
programs because it avoids the use of small Function objects.
The FutureTransformer must implement either flatMap
or map
and may optionally implement handle
. Failing to
implement a method will result in a run-time error (AbstractMethodError
).
addEventListener for a Java friendly way to perform side-effects.
transform for a Scala API.
Convert this Future[A]
to a Future[Unit]
by discarding the result.
Convert this Future[A]
to a Future[Unit]
by discarding the result.
failed futures will remain as is.
Populate the Promise with the given Try.
Populate the Promise with the given Try.
Populate the Promise with the given Try. The Try can either be a
value or an exception. setValue
and setException
are generally
more readable methods to use.
true only if the result is updated, false if it was already set.
Invoking updateIfEmpty
without checking the boolean result is almost
never the right approach. Doing so is generally unsafe unless race
conditions are acceptable.
Convert this Future[A]
to a Future[Void]
by discarding the result.
Convert this Future[A]
to a Future[Void]
by discarding the result.
failed futures will remain as is.
Returns a Future[Boolean]
indicating whether two Futures are equivalent.
Returns a Future[Boolean]
indicating whether two Futures are equivalent.
Note that
Future.exception(e).willEqual(Future.exception(e)) == Future.value(true)
.
Future.exception(e).willEqual(Future.exception(e)) == Future.value(true) }}}
Returns a new Future that fails if it is not satisfied in time.
Returns a new Future that fails if it is not satisfied in time.
Note: On timeout, the underlying future is not interrupted.
to run timeout on.
indicates how long you are willing to wait for the result to be available.
exception to throw.
Returns a new Future that fails if it is not satisfied in time.
Returns a new Future that fails if it is not satisfied in time.
Note: On timeout, the underlying future is not interrupted.
Returns a new Future that fails if it is not satisfied in time.
Returns a new Future that fails if it is not satisfied in time.
Same as the other within
, but with an implicit timer. Sometimes this is more convenient.
Note: On timeout, the underlying future is not interrupted.
A writeable com.twitter.util.Future that supports merging. Callbacks (responders) of Promises are scheduled with com.twitter.concurrent.Scheduler.
Implementation details
A Promise is in one of six states:
Waiting
,Interruptible
,Interrupted
,Transforming
,Done
andLinked
whereInterruptible
,Interrupted
, andTransforming
are variants ofWaiting
to deal with future interrupts. Promises are concurrency-safe, using lock-free operations throughout. Callback dispatch is scheduled with Scheduler.Waiters (i.e., continuations) are stored in a Promise.WaitQueue and executed in the LIFO order.
Promise.become
merges two promises: they are declared equivalent.become
merges the states of the two promises, and links one to the other. Thus promises support the analog to tail-call elimination: no space leak is incurred fromflatMap
in the tail position since intermediate promises are merged into the root promise.