2011-09-19 15:21:18 +02:00
2009-05-25 14:48:43 +02:00
/* *
2011-07-14 16:03:08 +02:00
* Copyright ( C ) 2009 - 2011 Typesafe Inc . < http : //www.typesafe.com>
2009-05-25 14:48:43 +02:00
*/
2010-10-26 12:49:25 +02:00
package akka.dispatch
2009-05-25 14:48:43 +02:00
2010-10-26 12:49:25 +02:00
import akka.AkkaException
2011-10-27 12:23:01 +02:00
import akka.event.Logging.Error
2011-11-09 14:56:05 +01:00
import akka.actor.Timeout
2011-08-26 17:25:18 +02:00
import scala.Option
import akka.japi. { Procedure , Function ⇒ JFunc , Option ⇒ JOption }
2010-10-31 19:27:55 +01:00
2011-04-21 15:12:47 -06:00
import scala.util.continuations._
2011-05-18 17:25:30 +02:00
import java.util.concurrent. { ConcurrentLinkedQueue , TimeUnit , Callable }
2011-12-02 17:13:46 +01:00
import java.util.concurrent.TimeUnit. { NANOSECONDS , MILLISECONDS }
2011-05-18 17:25:30 +02:00
import java.lang. { Iterable ⇒ JIterable }
import java.util. { LinkedList ⇒ JLinkedList }
2011-04-27 00:38:10 +02:00
import scala.annotation.tailrec
2011-04-28 20:53:45 -06:00
import scala.collection.mutable.Stack
2011-07-10 20:18:43 +02:00
import akka.util. { Switch , Duration , BoxedType }
2011-11-09 15:25:14 +01:00
import java.util.concurrent.atomic. { AtomicReferenceFieldUpdater , AtomicInteger , AtomicBoolean }
2009-05-25 14:48:43 +02:00
2011-08-08 15:38:22 +02:00
class FutureTimeoutException ( message : String , cause : Throwable = null ) extends AkkaException ( message , cause ) {
def this ( message : String ) = this ( message , null )
}
2009-06-10 20:04:33 +02:00
2011-12-02 09:26:56 +01:00
class FutureFactory ( ) ( implicit dispatcher : MessageDispatcher , timeout : Timeout ) {
2010-02-23 10:05:47 +01:00
2011-03-22 17:20:35 +01:00
/* *
* Java API , equivalent to Future . apply
*/
2011-02-28 16:29:03 -07:00
def future [ T ] ( body : Callable [ T ] ) : Future [ T ] =
2011-10-06 21:19:46 +02:00
Future ( body . call , timeout )
2011-02-28 16:29:03 -07:00
2011-06-18 23:23:47 -06:00
/* *
* Java API , equivalent to Future . apply
*/
def future [ T ] ( body : Callable [ T ] , timeout : Timeout ) : Future [ T ] =
Future ( body . call , timeout )
2011-03-22 17:20:35 +01:00
/* *
* Java API , equivalent to Future . apply
*/
2011-02-28 16:29:03 -07:00
def future [ T ] ( body : Callable [ T ] , timeout : Long ) : Future [ T ] =
Future ( body . call , timeout )
2010-11-12 14:04:06 +01:00
/* *
2011-03-22 17:20:35 +01:00
* Java API , equivalent to Future . apply
2010-11-12 14:04:06 +01:00
*/
2011-03-22 17:20:35 +01:00
def future [ T ] ( body : Callable [ T ] , dispatcher : MessageDispatcher ) : Future [ T ] =
2011-10-06 21:19:46 +02:00
Future ( body . call ) ( dispatcher , timeout )
2010-03-01 22:03:17 +01:00
2011-06-18 23:23:47 -06:00
/* *
* Java API , equivalent to Future . apply
*/
def future [ T ] ( body : Callable [ T ] , timeout : Timeout , dispatcher : MessageDispatcher ) : Future [ T ] =
2011-06-25 14:20:54 -06:00
Future ( body . call ) ( dispatcher , timeout )
2011-06-18 23:23:47 -06:00
2010-10-26 16:40:09 +02:00
/* *
2011-03-22 17:20:35 +01:00
* Java API , equivalent to Future . apply
2010-10-26 16:40:09 +02:00
*/
2011-03-22 17:20:35 +01:00
def future [ T ] ( body : Callable [ T ] , timeout : Long , dispatcher : MessageDispatcher ) : Future [ T ] =
2011-06-25 14:20:54 -06:00
Future ( body . call ) ( dispatcher , timeout )
2010-11-12 12:54:48 +01:00
2011-08-26 17:25:18 +02:00
/* *
* Java API .
* Returns a Future that will hold the optional result of the first Future with a result that matches the predicate
*/
def find [ T <: AnyRef ] ( futures : JIterable [ Future [ T ] ] , predicate : JFunc [ T , java . lang . Boolean ] , timeout : Timeout ) : Future [ JOption [ T ] ] = {
val pred : T ⇒ Boolean = predicate . apply ( _ )
2011-10-06 21:19:46 +02:00
Future . find [ T ] ( ( scala . collection . JavaConversions . iterableAsScalaIterable ( futures ) ) , timeout ) ( pred ) . map ( JOption . fromScalaOption ( _ ) ) ( timeout )
2011-08-26 17:25:18 +02:00
}
2011-10-06 21:19:46 +02:00
def find [ T <: AnyRef ] ( futures : JIterable [ Future [ T ] ] , predicate : JFunc [ T , java . lang . Boolean ] ) : Future [ JOption [ T ] ] = find ( futures , predicate , timeout )
2011-03-22 22:12:16 +01:00
/* *
2011-03-30 21:19:26 +02:00
* Java API .
2011-03-22 22:12:16 +01:00
* Returns a Future to the result of the first future in the list that is completed
*/
2011-08-26 17:25:18 +02:00
def firstCompletedOf [ T <: AnyRef ] ( futures : JIterable [ Future [ T ] ] , timeout : Timeout ) : Future [ T ] =
2011-09-08 15:54:06 +02:00
Future . firstCompletedOf ( scala . collection . JavaConversions . iterableAsScalaIterable ( futures ) , timeout )
2011-01-24 16:37:08 +01:00
2011-10-06 21:19:46 +02:00
def firstCompletedOf [ T <: AnyRef ] ( futures : JIterable [ Future [ T ] ] ) : Future [ T ] = firstCompletedOf ( futures , timeout )
2011-03-22 22:12:16 +01:00
/* *
* Java API
* A non - blocking fold over the specified futures .
* The fold is performed on the thread where the last future is completed ,
* the result will be the first failure of any of the futures , or any failure in the actual fold ,
* or the result of the fold .
*/
2011-06-18 23:23:47 -06:00
def fold [ T <: AnyRef , R <: AnyRef ] ( zero : R , timeout : Timeout , futures : java.lang.Iterable [ Future [ T ] ] , fun : akka.japi.Function2 [ R , T , R ] ) : Future [ R ] =
2011-10-06 21:19:46 +02:00
Future . fold ( scala . collection . JavaConversions . iterableAsScalaIterable ( futures ) , timeout ) ( zero ) ( fun . apply _ )
2011-03-22 22:12:16 +01:00
2011-06-18 23:23:47 -06:00
def fold [ T <: AnyRef , R <: AnyRef ] ( zero : R , timeout : Long , futures : java.lang.Iterable [ Future [ T ] ] , fun : akka.japi.Function2 [ R , T , R ] ) : Future [ R ] = fold ( zero , timeout : Timeout , futures , fun )
2011-10-06 21:19:46 +02:00
def fold [ T <: AnyRef , R <: AnyRef ] ( zero : R , futures : java.lang.Iterable [ Future [ T ] ] , fun : akka.japi.Function2 [ R , T , R ] ) : Future [ R ] = fold ( zero , timeout , futures , fun )
2011-06-18 23:23:47 -06:00
2011-03-22 22:12:16 +01:00
/* *
2011-03-30 21:19:26 +02:00
* Java API .
2011-03-22 22:12:16 +01:00
* Initiates a fold over the supplied futures where the fold - zero is the result value of the Future that 's completed first
*/
2011-06-18 23:23:47 -06:00
def reduce [ T <: AnyRef , R >: T ] ( futures : java.lang.Iterable [ Future [ T ] ] , timeout : Timeout , fun : akka.japi.Function2 [ R , T , T ] ) : Future [ R ] =
2011-09-08 15:54:06 +02:00
Future . reduce ( scala . collection . JavaConversions . iterableAsScalaIterable ( futures ) , timeout ) ( fun . apply _ )
2011-03-22 22:12:16 +01:00
2011-06-18 23:23:47 -06:00
def reduce [ T <: AnyRef , R >: T ] ( futures : java.lang.Iterable [ Future [ T ] ] , timeout : Long , fun : akka.japi.Function2 [ R , T , T ] ) : Future [ R ] = reduce ( futures , timeout : Timeout , fun )
2011-10-06 21:19:46 +02:00
def reduce [ T <: AnyRef , R >: T ] ( futures : java.lang.Iterable [ Future [ T ] ] , fun : akka.japi.Function2 [ R , T , T ] ) : Future [ R ] = reduce ( futures , timeout , fun )
2011-04-15 13:09:53 -06:00
/* *
* Java API .
2011-09-08 15:54:06 +02:00
* Simple version of Future . traverse . Transforms a java . lang . Iterable [ Future [ A ] ] into a Future [ java . lang . Iterable [ A ] ] .
2011-04-15 13:09:53 -06:00
* Useful for reducing many Futures into a single Future .
*/
2011-10-06 21:19:46 +02:00
def sequence [ A ] ( in : JIterable [ Future [ A ] ] , timeout : Timeout ) : Future [ JIterable [ A ] ] = {
implicit val t = timeout
2011-05-18 17:25:30 +02:00
scala . collection . JavaConversions . iterableAsScalaIterable ( in ) . foldLeft ( Future ( new JLinkedList [ A ] ( ) ) ) ( ( fr , fa ) ⇒
for ( r ← fr ; a ← fa ) yield {
2011-04-15 13:09:53 -06:00
r add a
r
} )
2011-10-06 21:19:46 +02:00
}
2011-01-24 16:37:08 +01:00
2011-10-06 21:19:46 +02:00
def sequence [ A ] ( in : JIterable [ Future [ A ] ] ) : Future [ JIterable [ A ] ] = sequence ( in , timeout )
2011-02-25 07:30:31 -07:00
2011-03-30 21:19:26 +02:00
/* *
2011-04-15 13:09:53 -06:00
* Java API .
2011-08-06 14:03:04 +02:00
* Transforms a java . lang . Iterable [ A ] into a Future [ java . lang . Iterable [ B ] ] using the provided Function A ⇒ Future [ B ] .
2011-04-03 10:40:06 -06:00
* This is useful for performing a parallel map . For example , to apply a function to all items of a list
2011-04-15 13:09:53 -06:00
* in parallel .
2011-03-30 21:19:26 +02:00
*/
2011-10-06 21:19:46 +02:00
def traverse [ A , B ] ( in : JIterable [ A ] , timeout : Timeout , fn : JFunc [ A , Future [ B ] ] ) : Future [ JIterable [ B ] ] = {
implicit val t = timeout
2011-05-18 17:25:30 +02:00
scala . collection . JavaConversions . iterableAsScalaIterable ( in ) . foldLeft ( Future ( new JLinkedList [ B ] ( ) ) ) { ( fr , a ) ⇒
2011-04-15 13:09:53 -06:00
val fb = fn ( a )
2011-05-18 17:25:30 +02:00
for ( r ← fr ; b ← fb ) yield {
2011-04-15 13:09:53 -06:00
r add b
r
}
}
2011-10-06 21:19:46 +02:00
}
def traverse [ A , B ] ( in : JIterable [ A ] , fn : JFunc [ A , Future [ B ] ] ) : Future [ JIterable [ B ] ] = traverse ( in , timeout , fn )
2011-04-15 13:09:53 -06:00
2010-02-23 10:05:47 +01:00
}
2011-02-28 11:47:39 -07:00
object Future {
2011-04-27 01:06:08 +02:00
2011-03-22 22:12:16 +01:00
/* *
* This method constructs and returns a Future that will eventually hold the result of the execution of the supplied body
* The execution is performed by the specified Dispatcher .
*/
2011-10-06 21:19:46 +02:00
def apply [ T ] ( body : ⇒ T ) ( implicit dispatcher : MessageDispatcher , timeout : Timeout ) : Future [ T ] = {
2011-07-26 22:23:16 -06:00
val promise = new DefaultPromise [ T ] ( timeout )
dispatcher dispatchTask { ( ) ⇒
promise complete {
try {
Right ( body )
} catch {
2011-11-30 10:20:57 +01:00
// FIXME catching all and continue isn't good for OOME, ticket #1418
2011-07-26 22:23:16 -06:00
case e ⇒ Left ( e )
}
}
}
promise
}
2011-04-15 13:09:53 -06:00
2011-06-25 14:20:54 -06:00
def apply [ T ] ( body : ⇒ T , timeout : Timeout ) ( implicit dispatcher : MessageDispatcher ) : Future [ T ] =
apply ( body ) ( dispatcher , timeout )
2011-08-02 13:01:10 -06:00
def apply [ T ] ( body : ⇒ T , timeout : Duration ) ( implicit dispatcher : MessageDispatcher ) : Future [ T ] =
apply ( body ) ( dispatcher , timeout )
2011-06-25 14:20:54 -06:00
def apply [ T ] ( body : ⇒ T , timeout : Long ) ( implicit dispatcher : MessageDispatcher ) : Future [ T ] =
apply ( body ) ( dispatcher , timeout )
2011-04-15 13:09:53 -06:00
import scala.collection.mutable.Builder
import scala.collection.generic.CanBuildFrom
/* *
* Simple version of Futures . traverse . Transforms a Traversable [ Future [ A ] ] into a Future [ Traversable [ A ] ] .
* Useful for reducing many Futures into a single Future .
*/
2011-10-06 21:19:46 +02:00
def sequence [ A , M [ _ ] <: Traversable [ _ ] ] ( in : M [ Future [ A ] ] ) ( implicit cbf : CanBuildFrom [ M [ Future [ A ] ] , A , M [ A ] ] , timeout : Timeout , dispatcher : MessageDispatcher ) : Future [ M [ A ] ] =
2011-06-25 14:20:54 -06:00
in . foldLeft ( new KeptPromise ( Right ( cbf ( in ) ) ) : Future [ Builder [ A , M [ A ] ] ] ) ( ( fr , fa ) ⇒ for ( r ← fr ; a ← fa . asInstanceOf [ Future [ A ] ] ) yield ( r += a ) ) . map ( _ . result )
2011-10-07 15:22:36 +02:00
2011-10-06 21:19:46 +02:00
def sequence [ A , M [ _ ] <: Traversable [ _ ] ] ( in : M [ Future [ A ] ] , timeout : Timeout ) ( implicit cbf : CanBuildFrom [ M [ Future [ A ] ] , A , M [ A ] ] , dispatcher : MessageDispatcher ) : Future [ M [ A ] ] =
sequence ( in ) ( cbf , timeout , dispatcher )
2011-04-15 13:09:53 -06:00
2011-09-08 15:54:06 +02:00
/* *
* Returns a Future to the result of the first future in the list that is completed
*/
2011-10-06 21:19:46 +02:00
def firstCompletedOf [ T ] ( futures : Iterable [ Future [ T ] ] ) ( implicit dispatcher : MessageDispatcher , timeout : Timeout ) : Future [ T ] = {
2011-09-08 15:54:06 +02:00
val futureResult = new DefaultPromise [ T ] ( timeout )
val completeFirst : Future [ T ] ⇒ Unit = _ . value . foreach ( futureResult complete _ )
futures . foreach ( _ onComplete completeFirst )
futureResult
}
2011-10-06 21:19:46 +02:00
def firstCompletedOf [ T ] ( futures : Iterable [ Future [ T ] ] , timeout : Timeout ) ( implicit dispatcher : MessageDispatcher ) : Future [ T ] =
firstCompletedOf ( futures ) ( dispatcher , timeout )
2011-10-07 15:22:36 +02:00
2011-09-08 15:54:06 +02:00
/* *
* Returns a Future that will hold the optional result of the first Future with a result that matches the predicate
*/
2011-10-06 21:19:46 +02:00
def find [ T ] ( futures : Iterable [ Future [ T ] ] ) ( predicate : T ⇒ Boolean ) ( implicit dispatcher : MessageDispatcher , timeout : Timeout ) : Future [ Option [ T ] ] = {
2011-09-08 15:54:06 +02:00
if ( futures . isEmpty ) new KeptPromise [ Option [ T ] ] ( Right ( None ) )
else {
val result = new DefaultPromise [ Option [ T ] ] ( timeout )
val ref = new AtomicInteger ( futures . size )
val search : Future [ T ] ⇒ Unit = f ⇒ try {
f . result . filter ( predicate ) . foreach ( r ⇒ result completeWithResult Some ( r ) )
} finally {
if ( ref . decrementAndGet == 0 )
result completeWithResult None
}
futures . foreach ( _ onComplete search )
result
}
}
2011-10-07 15:22:36 +02:00
def find [ T ] ( futures : Iterable [ Future [ T ] ] , timeout : Timeout ) ( predicate : T ⇒ Boolean ) ( implicit dispatcher : MessageDispatcher ) : Future [ Option [ T ] ] =
2011-10-06 21:19:46 +02:00
find ( futures ) ( predicate ) ( dispatcher , timeout )
2011-10-07 15:22:36 +02:00
2011-09-08 15:54:06 +02:00
/* *
* A non - blocking fold over the specified futures .
* The fold is performed on the thread where the last future is completed ,
* the result will be the first failure of any of the futures , or any failure in the actual fold ,
* or the result of the fold .
* Example :
* < pre >
* val result = Futures . fold ( 0 ) ( futures ) ( _ + _ ) . await . result
* </ pre >
*/
2011-10-06 21:19:46 +02:00
def fold [ T , R ] ( futures : Iterable [ Future [ T ] ] ) ( zero : R ) ( foldFun : ( R , T ) ⇒ R ) ( implicit dispatcher : MessageDispatcher , timeout : Timeout ) : Future [ R ] = {
2011-09-08 15:54:06 +02:00
if ( futures . isEmpty ) {
new KeptPromise [ R ] ( Right ( zero ) )
} else {
val result = new DefaultPromise [ R ] ( timeout )
val results = new ConcurrentLinkedQueue [ T ] ( )
val done = new Switch ( false )
val allDone = futures . size
val aggregate : Future [ T ] ⇒ Unit = f ⇒ if ( done . isOff && ! result . isCompleted ) { //TODO: This is an optimization, is it premature?
f . value . get match {
case Right ( value ) ⇒
val added = results add value
if ( added && results . size == allDone ) { //Only one thread can get here
if ( done . switchOn ) {
try {
val i = results . iterator
var currentValue = zero
while ( i . hasNext ) { currentValue = foldFun ( currentValue , i . next ) }
result completeWithResult currentValue
} catch {
case e : Exception ⇒
2011-11-18 11:59:43 +01:00
dispatcher . prerequisites . eventStream . publish ( Error ( e , "Future.fold" , e . getMessage ) )
2011-09-08 15:54:06 +02:00
result completeWithException e
} finally {
results . clear
}
}
}
case Left ( exception ) ⇒
if ( done . switchOn ) {
result completeWithException exception
results . clear
}
}
}
futures foreach { _ onComplete aggregate }
result
}
}
2011-10-07 15:22:36 +02:00
2011-10-06 21:19:46 +02:00
def fold [ T , R ] ( futures : Iterable [ Future [ T ] ] , timeout : Timeout ) ( zero : R ) ( foldFun : ( R , T ) ⇒ R ) ( implicit dispatcher : MessageDispatcher ) : Future [ R ] =
fold ( futures ) ( zero ) ( foldFun ) ( dispatcher , timeout )
2011-09-08 15:54:06 +02:00
/* *
* Initiates a fold over the supplied futures where the fold - zero is the result value of the Future that 's completed first
* Example :
* < pre >
* val result = Futures . reduce ( futures ) ( _ + _ ) . await . result
* </ pre >
*/
2011-10-06 21:19:46 +02:00
def reduce [ T , R >: T ] ( futures : Iterable [ Future [ T ] ] ) ( op : ( R , T ) ⇒ T ) ( implicit dispatcher : MessageDispatcher , timeout : Timeout ) : Future [ R ] = {
2011-09-08 15:54:06 +02:00
if ( futures . isEmpty )
new KeptPromise [ R ] ( Left ( new UnsupportedOperationException ( "empty reduce left" ) ) )
else {
val result = new DefaultPromise [ R ] ( timeout )
val seedFound = new AtomicBoolean ( false )
val seedFold : Future [ T ] ⇒ Unit = f ⇒ {
if ( seedFound . compareAndSet ( false , true ) ) { //Only the first completed should trigger the fold
f . value . get match {
2011-10-06 21:19:46 +02:00
case Right ( value ) ⇒ result . completeWith ( fold ( futures . filterNot ( _ eq f ) ) ( value ) ( op ) )
2011-09-08 15:54:06 +02:00
case Left ( exception ) ⇒ result . completeWithException ( exception )
}
}
}
for ( f ← futures ) f onComplete seedFold //Attach the listener to the Futures
result
}
}
2011-10-07 15:22:36 +02:00
2011-10-06 21:19:46 +02:00
def reduce [ T , R >: T ] ( futures : Iterable [ Future [ T ] ] , timeout : Timeout ) ( op : ( R , T ) ⇒ T ) ( implicit dispatcher : MessageDispatcher ) : Future [ R ] =
reduce ( futures ) ( op ) ( dispatcher , timeout )
2011-09-08 15:54:06 +02:00
2011-04-15 13:09:53 -06:00
/* *
2011-08-06 14:03:04 +02:00
* Transforms a Traversable [ A ] into a Future [ Traversable [ B ] ] using the provided Function A ⇒ Future [ B ] .
2011-04-15 13:09:53 -06:00
* This is useful for performing a parallel map . For example , to apply a function to all items of a list
* in parallel :
* < pre >
2011-08-06 14:03:04 +02:00
* val myFutureList = Futures . traverse ( myList ) ( x ⇒ Future ( myFunc ( x ) ) )
2011-04-15 13:09:53 -06:00
* </ pre >
*/
2011-10-06 21:19:46 +02:00
def traverse [ A , B , M [ _ ] <: Traversable [ _ ] ] ( in : M [ A ] ) ( fn : A ⇒ Future [ B ] ) ( implicit cbf : CanBuildFrom [ M [ A ] , B , M [ B ] ] , timeout : Timeout , dispatcher : MessageDispatcher ) : Future [ M [ B ] ] =
2011-06-25 14:20:54 -06:00
in . foldLeft ( new KeptPromise ( Right ( cbf ( in ) ) ) : Future [ Builder [ B , M [ B ] ] ] ) { ( fr , a ) ⇒
2011-04-15 13:09:53 -06:00
val fb = fn ( a . asInstanceOf [ A ] )
2011-05-18 17:25:30 +02:00
for ( r ← fr ; b ← fb ) yield ( r += b )
2011-04-15 13:09:53 -06:00
} . map ( _ . result )
2011-10-07 15:22:36 +02:00
2011-10-06 21:19:46 +02:00
def traverse [ A , B , M [ _ ] <: Traversable [ _ ] ] ( in : M [ A ] , timeout : Timeout ) ( fn : A ⇒ Future [ B ] ) ( implicit cbf : CanBuildFrom [ M [ A ] , B , M [ B ] ] , dispatcher : MessageDispatcher ) : Future [ M [ B ] ] =
traverse ( in ) ( fn ) ( cbf , timeout , dispatcher )
2011-06-25 14:20:54 -06:00
2011-04-23 12:57:28 -06:00
/* *
* Captures a block that will be transformed into 'Continuation Passing Style ' using Scala 's Delimited
* Continuations plugin .
*
* Within the block , the result of a Future may be accessed by calling Future . apply . At that point
* execution is suspended with the rest of the block being stored in a continuation until the result
* of the Future is available . If an Exception is thrown while processing , it will be contained
* within the resulting Future .
*
* This allows working with Futures in an imperative style without blocking for each result .
*
2011-05-23 11:31:01 +02:00
* Completing a Future using 'Promise << Future ' will also suspend execution until the
2011-04-23 12:57:28 -06:00
* value of the other Future is available .
*
* The Delimited Continuations compiler plugin must be enabled in order to use this method .
*/
2011-07-26 22:23:16 -06:00
def flow [ A ] ( body : ⇒ A @cps [ Future [ Any ] ] ) ( implicit dispatcher : MessageDispatcher , timeout : Timeout ) : Future [ A ] = {
2011-05-03 18:48:42 -06:00
val future = Promise [ A ] ( timeout )
2011-08-05 08:55:36 -06:00
dispatchTask ( { ( ) ⇒
( reify ( body ) foreachFull ( future completeWithResult , future completeWithException ) : Future [ Any ] ) onException {
case e : Exception ⇒ future completeWithException e
}
} , true )
2011-05-02 16:56:42 -06:00
future
2011-05-02 14:44:40 -06:00
}
2011-10-07 15:22:36 +02:00
// TODO make variant of flow(timeout)(body) which does NOT break type inference
2011-08-05 08:55:36 -06:00
2011-10-27 20:04:32 -06:00
/* *
2011-11-05 12:48:19 -06:00
* Assures that any Future tasks initiated in the current thread will be
* executed asynchronously , including any tasks currently queued to be
* executed in the current thread . This is needed if the current task may
* block , causing delays in executing the remaining tasks which in some
* cases may cause a deadlock .
2011-10-27 20:04:32 -06:00
*
2011-11-05 12:48:19 -06:00
* Note : Calling ' Future . await ' will automatically trigger this method .
*
* For example , in the following block of code the call to 'latch. open '
* might not be executed until after the call to 'latch. await ' , causing
* a deadlock . By adding 'Future. blocking ( ) ' the call to 'latch. open '
* will instead be dispatched separately from the current block , allowing
* it to be run in parallel :
2011-10-27 20:04:32 -06:00
* < pre >
* val latch = new StandardLatch
* val future = Future ( ) map { _ ⇒
2011-11-05 12:48:19 -06:00
* Future . blocking ( )
2011-10-27 20:04:32 -06:00
* val nested = Future ( )
* nested foreach ( _ ⇒ latch . open )
* latch . await
* }
* </ pre >
*/
2011-11-05 12:48:19 -06:00
def blocking ( ) ( implicit dispatcher : MessageDispatcher ) : Unit =
2011-10-27 20:04:32 -06:00
_taskStack . get match {
case Some ( taskStack ) if taskStack . nonEmpty ⇒
val tasks = taskStack . elems
taskStack . clear ( )
2011-11-05 12:48:19 -06:00
_taskStack set None
2011-10-27 20:04:32 -06:00
dispatchTask ( ( ) ⇒ _taskStack . get . get . elems = tasks , true )
2011-11-05 12:48:19 -06:00
case Some ( _ ) ⇒ _taskStack set None
case _ ⇒ // already None
2011-10-27 20:04:32 -06:00
}
2011-08-05 08:55:36 -06:00
private val _taskStack = new ThreadLocal [ Option [ Stack [ ( ) ⇒ Unit ] ] ] ( ) {
override def initialValue = None
}
private [ akka ] def dispatchTask ( task : ( ) ⇒ Unit , force : Boolean = false ) ( implicit dispatcher : MessageDispatcher ) : Unit =
_taskStack . get match {
case Some ( taskStack ) if ! force ⇒ taskStack push task
case _ ⇒
dispatcher dispatchTask { ( ) ⇒
try {
val taskStack = Stack [ ( ) ⇒ Unit ] ( task )
_taskStack set Some ( taskStack )
while ( taskStack . nonEmpty ) {
val next = taskStack . pop ( )
try {
next . apply ( )
} catch {
2011-11-30 10:20:57 +01:00
case e ⇒
// FIXME catching all and continue isn't good for OOME, ticket #1418
dispatcher . prerequisites . eventStream . publish ( Error ( e , "Future.dispatchTask" , "Failed to dispatch task, due to: " + e . getMessage ) )
2011-08-05 08:55:36 -06:00
}
}
} finally { _taskStack set None }
}
}
2011-02-28 11:47:39 -07:00
}
2011-08-05 08:55:36 -06:00
sealed trait Future [ + T ] extends japi . Future [ T ] {
2011-03-22 22:12:16 +01:00
2011-08-02 10:19:49 -06:00
implicit def dispatcher : MessageDispatcher
2011-03-22 22:12:16 +01:00
/* *
2011-04-23 12:57:28 -06:00
* For use only within a Future . flow block or another compatible Delimited Continuations reset block .
*
* Returns the result of this Future without blocking , by suspending execution and storing it as a
* continuation until the result is available .
2011-03-22 22:12:16 +01:00
*/
2011-08-05 08:55:36 -06:00
def apply ( ) ( implicit timeout : Timeout ) : T @ cps [ Future [ Any ] ] = shift ( this flatMap ( _ : T ⇒ Future [ Any ] ) )
2011-03-22 22:12:16 +01:00
/* *
2011-04-26 10:49:52 +02:00
* Blocks awaiting completion of this Future , then returns the resulting value ,
* or throws the completed exception
*
* Scala & Java API
*
* throws FutureTimeoutException if this Future times out when waiting for completion
2011-03-22 22:12:16 +01:00
*/
2011-04-21 15:12:47 -06:00
def get : T = this . await . resultOrException . get
2011-03-22 22:12:16 +01:00
2011-02-23 19:57:42 -07:00
/* *
* Blocks the current thread until the Future has been completed or the
* timeout has expired . In the case of the timeout expiring a
* FutureTimeoutException will be thrown .
*/
2011-05-18 17:25:30 +02:00
def await : Future [ T ]
2010-10-31 19:27:55 +01:00
2011-04-27 15:34:42 +02:00
/* *
* Blocks the current thread until the Future has been completed or the
2011-09-02 08:47:28 +02:00
* timeout has expired , additionally bounding the waiting period according to
* the < code > atMost </ code > parameter . The timeout will be the lesser value of
* 'atMost' and the timeout supplied at the constructuion of this Future . In
* the case of the timeout expiring a FutureTimeoutException will be thrown .
* Other callers of this method are not affected by the additional bound
* imposed by < code > atMost </ code > .
2011-04-27 15:34:42 +02:00
*/
2011-05-18 17:25:30 +02:00
def await ( atMost : Duration ) : Future [ T ]
2011-04-27 15:34:42 +02:00
2011-08-09 21:37:39 +02:00
/* *
* Await completion of this Future and return its value if it conforms to A 's
* erased type . Will throw a ClassCastException if the value does not
* conform , or any exception the Future was completed with . Will return None
* in case of a timeout .
*/
def as [ A ] ( implicit m : Manifest [ A ] ) : Option [ A ] = {
try await catch { case _ : FutureTimeoutException ⇒ }
value match {
case None ⇒ None
case Some ( Left ( ex ) ) ⇒ throw ex
2011-09-26 15:33:57 +02:00
case Some ( Right ( v ) ) ⇒
try { Some ( BoxedType ( m . erasure ) . cast ( v ) . asInstanceOf [ A ] ) } catch {
case c : ClassCastException ⇒
if ( v . asInstanceOf [ AnyRef ] eq null ) throw new ClassCastException ( "null cannot be cast to " + m . erasure )
2011-10-28 23:11:35 +02:00
else throw new ClassCastException ( "'" + v + "' of class " + v . asInstanceOf [ AnyRef ] . getClass + " cannot be cast to " + m . erasure )
2011-09-26 15:33:57 +02:00
}
2011-08-09 21:37:39 +02:00
}
}
/* *
* Await completion of this Future and return its value if it conforms to A 's
* erased type , None otherwise . Will throw any exception the Future was
* completed with . Will return None in case of a timeout .
*/
def asSilently [ A ] ( implicit m : Manifest [ A ] ) : Option [ A ] = {
try await catch { case _ : FutureTimeoutException ⇒ }
value match {
case None ⇒ None
case Some ( Left ( ex ) ) ⇒ throw ex
case Some ( Right ( v ) ) ⇒
try Some ( BoxedType ( m . erasure ) . cast ( v ) . asInstanceOf [ A ] )
catch { case _ : ClassCastException ⇒ None }
}
}
2011-02-23 19:57:42 -07:00
/* *
* Tests whether this Future has been completed .
*/
2011-02-13 19:59:54 -07:00
final def isCompleted : Boolean = value . isDefined
2010-10-31 19:27:55 +01:00
2011-02-23 19:57:42 -07:00
/* *
* Tests whether this Future 's timeout has expired .
*
* Note that an expired Future may still contain a value , or it may be
* completed with a value .
*/
2009-05-25 14:48:43 +02:00
def isExpired : Boolean
2010-10-31 19:27:55 +01:00
2011-06-18 23:23:47 -06:00
def timeout : Timeout
2011-02-23 19:57:42 -07:00
/* *
* This Future 's timeout in nanoseconds .
*/
2011-06-18 23:23:47 -06:00
def timeoutInNanos = if ( timeout . duration . isFinite ) timeout . duration . toNanos else Long . MaxValue
2010-10-31 19:27:55 +01:00
2011-02-23 19:57:42 -07:00
/* *
* The contained value of this Future . Before this Future is completed
* the value will be None . After completion the value will be Some ( Right ( t ) )
* if it contains a valid result , or Some ( Left ( error ) ) if it contains
* an exception .
*/
2011-02-11 14:46:39 -07:00
def value : Option [ Either [ Throwable , T ] ]
2011-02-23 19:57:42 -07:00
/* *
* Returns the successful result of this Future if it exists .
*/
2011-08-06 14:03:04 +02:00
final def result : Option [ T ] = value match {
2011-08-06 13:32:03 -06:00
case Some ( Right ( r ) ) ⇒ Some ( r )
case _ ⇒ None
2011-02-13 19:59:54 -07:00
}
2010-10-31 19:27:55 +01:00
2011-02-23 19:57:42 -07:00
/* *
* Returns the contained exception of this Future if it exists .
*/
2011-08-06 14:03:04 +02:00
final def exception : Option [ Throwable ] = value match {
2011-08-06 13:32:03 -06:00
case Some ( Left ( e ) ) ⇒ Some ( e )
case _ ⇒ None
2011-02-13 19:59:54 -07:00
}
2010-10-31 19:27:55 +01:00
2011-02-23 19:57:42 -07:00
/* *
* When this Future is completed , apply the provided function to the
* Future . If the Future has already been completed , this will apply
2011-09-16 21:19:41 +02:00
* immediately . Will not be called in case of a timeout , which also holds if
* corresponding Promise is attempted to complete after expiry . Multiple
* callbacks may be registered ; there is no guarantee that they will be
* executed in a particular order .
2011-02-23 19:57:42 -07:00
*/
2011-06-13 22:36:46 +02:00
def onComplete ( func : Future [ T ] ⇒ Unit ) : this.type
2010-11-12 12:11:53 +01:00
2011-02-13 21:11:37 -07:00
/* *
2011-04-23 08:11:31 +02:00
* When the future is completed with a valid result , apply the provided
2011-09-16 21:19:41 +02:00
* PartialFunction to the result . See `onComplete` for more details .
2011-03-30 21:19:26 +02:00
* < pre >
2011-08-06 14:03:04 +02:00
* future onResult {
* case Foo ⇒ target ! "foo"
* case Bar ⇒ target ! "bar"
2011-06-02 13:33:49 -07:00
* }
2011-03-30 21:19:26 +02:00
* </ pre >
2011-02-13 21:11:37 -07:00
*/
2011-08-06 14:03:04 +02:00
final def onResult ( pf : PartialFunction [ T , Unit ] ) : this . type = onComplete {
_ . value match {
case Some ( Right ( r ) ) if pf isDefinedAt r ⇒ pf ( r )
case _ ⇒
2011-06-02 13:33:49 -07:00
}
}
/* *
* When the future is completed with an exception , apply the provided
2011-09-16 21:19:41 +02:00
* PartialFunction to the exception . See `onComplete` for more details .
2011-06-02 13:33:49 -07:00
* < pre >
2011-08-06 14:03:04 +02:00
* future onException {
* case NumberFormatException ⇒ target ! "wrong format"
2011-06-02 13:33:49 -07:00
* }
* </ pre >
*/
2011-08-06 14:03:04 +02:00
final def onException ( pf : PartialFunction [ Throwable , Unit ] ) : this . type = onComplete {
_ . value match {
case Some ( Left ( ex ) ) if pf isDefinedAt ex ⇒ pf ( ex )
case _ ⇒
2011-02-13 21:11:37 -07:00
}
}
2011-06-17 06:51:40 -06:00
def onTimeout ( func : Future [ T ] ⇒ Unit ) : this.type
2011-06-20 16:22:46 -06:00
def orElse [ A >: T ] ( fallback : ⇒ A ) : Future [ A ]
2011-04-25 16:14:07 -06:00
/* *
* Creates a new Future that will handle any matching Throwable that this
* Future might contain . If there is no match , or if this Future contains
* a valid result then the new Future will contain the same .
* Example :
* < pre >
2011-09-01 14:58:18 +02:00
* Future ( 6 / 0 ) recover { case e : ArithmeticException ⇒ 0 } // result: 0
* Future ( 6 / 0 ) recover { case e : NotFoundException ⇒ 0 } // result: exception
* Future ( 6 / 2 ) recover { case e : ArithmeticException ⇒ 0 } // result: 3
2011-04-25 16:14:07 -06:00
* </ pre >
*/
2011-08-02 10:19:49 -06:00
final def recover [ A >: T ] ( pf : PartialFunction [ Throwable , A ] ) ( implicit timeout : Timeout ) : Future [ A ] = {
2011-07-27 22:20:02 -06:00
val future = new DefaultPromise [ A ] ( timeout )
2011-08-06 14:03:04 +02:00
onComplete {
_ . value . get match {
case Left ( e ) if pf isDefinedAt e ⇒ future . complete ( try { Right ( pf ( e ) ) } catch { case x : Exception ⇒ Left ( x ) } )
case otherwise ⇒ future complete otherwise
2011-06-18 20:13:13 -06:00
}
2011-07-27 22:20:02 -06:00
}
future
2011-06-18 20:13:13 -06:00
}
2011-04-25 16:14:07 -06:00
2011-02-23 19:57:42 -07:00
/* *
* Creates a new Future by applying a function to the successful result of
* this Future . If this Future is completed with an exception then the new
* Future will also contain this exception .
2011-03-30 21:19:26 +02:00
* Example :
* < pre >
* val future1 = for {
2011-06-13 13:43:21 +02:00
* a : Int <- actor ? " Hello " // returns 5
* b : String <- actor ? a // returns "10"
* c : String <- actor ? 7 // returns "14"
2011-03-30 21:19:26 +02:00
* } yield b + "-" + c
* </ pre >
2011-02-23 19:57:42 -07:00
*/
2011-08-02 10:19:49 -06:00
final def map [ A ] ( f : T ⇒ A ) ( implicit timeout : Timeout ) : Future [ A ] = {
2011-07-27 22:20:02 -06:00
val future = new DefaultPromise [ A ] ( timeout )
2011-08-06 14:03:04 +02:00
onComplete {
_ . value . get match {
case l : Left [ _ , _ ] ⇒ future complete l . asInstanceOf [ Either [ Throwable , A ] ]
case Right ( res ) ⇒
future complete ( try {
Right ( f ( res ) )
} catch {
case e : Exception ⇒
2011-11-18 11:59:43 +01:00
dispatcher . prerequisites . eventStream . publish ( Error ( e , "Future.map" , e . getMessage ) )
2011-08-06 14:03:04 +02:00
Left ( e )
} )
2011-06-18 20:13:13 -06:00
}
2011-07-27 22:20:02 -06:00
}
future
2011-06-18 20:13:13 -06:00
}
2011-02-21 17:24:51 -07:00
2011-06-13 22:36:46 +02:00
/* *
* Creates a new Future [ A ] which is completed with this Future 's result if
* that conforms to A 's erased type or a ClassCastException otherwise .
*/
2011-08-02 10:19:49 -06:00
final def mapTo [ A ] ( implicit m : Manifest [ A ] , timeout : Timeout = this . timeout ) : Future [ A ] = {
2011-07-27 22:20:02 -06:00
val fa = new DefaultPromise [ A ] ( timeout )
onComplete { ft ⇒
fa complete ( ft . value . get match {
case l : Left [ _ , _ ] ⇒ l . asInstanceOf [ Either [ Throwable , A ] ]
case Right ( t ) ⇒
try {
Right ( BoxedType ( m . erasure ) . cast ( t ) . asInstanceOf [ A ] )
} catch {
case e : ClassCastException ⇒ Left ( e )
}
2011-06-18 20:13:13 -06:00
} )
2011-07-27 22:20:02 -06:00
}
fa
2011-06-18 20:13:13 -06:00
}
2011-06-13 22:36:46 +02:00
2011-02-23 19:57:42 -07:00
/* *
* Creates a new Future by applying a function to the successful result of
* this Future , and returns the result of the function as the new Future .
* If this Future is completed with an exception then the new Future will
* also contain this exception .
2011-03-30 21:19:26 +02:00
* Example :
* < pre >
* val future1 = for {
2011-06-13 13:43:21 +02:00
* a : Int <- actor ? " Hello " // returns 5
* b : String <- actor ? a // returns "10"
* c : String <- actor ? 7 // returns "14"
2011-03-30 21:19:26 +02:00
* } yield b + "-" + c
* </ pre >
2011-02-23 19:57:42 -07:00
*/
2011-08-02 10:19:49 -06:00
final def flatMap [ A ] ( f : T ⇒ Future [ A ] ) ( implicit timeout : Timeout ) : Future [ A ] = {
2011-07-27 22:20:02 -06:00
val future = new DefaultPromise [ A ] ( timeout )
2011-08-06 14:03:04 +02:00
2011-07-27 22:20:02 -06:00
onComplete {
_ . value . get match {
2011-08-06 14:03:04 +02:00
case l : Left [ _ , _ ] ⇒ future complete l . asInstanceOf [ Either [ Throwable , A ] ]
case Right ( r ) ⇒ try {
future . completeWith ( f ( r ) )
} catch {
case e : Exception ⇒
2011-11-18 11:59:43 +01:00
dispatcher . prerequisites . eventStream . publish ( Error ( e , "Future.flatMap" , e . getMessage ) )
2011-08-06 14:03:04 +02:00
future complete Left ( e )
2011-06-18 20:13:13 -06:00
}
}
2011-07-27 22:20:02 -06:00
}
future
2011-06-18 20:13:13 -06:00
}
2011-02-21 17:24:51 -07:00
2011-05-26 19:33:03 +02:00
final def foreach ( f : T ⇒ Unit ) : Unit = onComplete {
2011-08-06 14:03:04 +02:00
_ . value . get match {
case Right ( r ) ⇒ f ( r )
case _ ⇒
2011-05-26 19:33:03 +02:00
}
}
2011-08-02 10:19:49 -06:00
final def withFilter ( p : T ⇒ Boolean ) ( implicit timeout : Timeout ) = new FutureWithFilter [ T ] ( this , p )
2011-05-26 19:33:03 +02:00
2011-06-25 14:20:54 -06:00
final class FutureWithFilter [ + A ] ( self : Future [ A ] , p : A ⇒ Boolean ) ( implicit timeout : Timeout ) {
2011-05-26 19:33:03 +02:00
def foreach ( f : A ⇒ Unit ) : Unit = self filter p foreach f
def map [ B ] ( f : A ⇒ B ) : Future [ B ] = self filter p map f
def flatMap [ B ] ( f : A ⇒ Future [ B ] ) : Future [ B ] = self filter p flatMap f
def withFilter ( q : A ⇒ Boolean ) : FutureWithFilter [ A ] = new FutureWithFilter [ A ] ( self , x ⇒ p ( x ) && q ( x ) )
2011-02-21 17:24:51 -07:00
}
2011-08-02 10:19:49 -06:00
final def filter ( p : T ⇒ Boolean ) ( implicit timeout : Timeout ) : Future [ T ] = {
2011-07-27 22:20:02 -06:00
val future = new DefaultPromise [ T ] ( timeout )
2011-08-06 14:03:04 +02:00
onComplete {
_ . value . get match {
case l : Left [ _ , _ ] ⇒ future complete l . asInstanceOf [ Either [ Throwable , T ] ]
case r @ Right ( res ) ⇒ future complete ( try {
if ( p ( res ) ) r else Left ( new MatchError ( res ) )
} catch {
case e : Exception ⇒
2011-11-18 11:59:43 +01:00
dispatcher . prerequisites . eventStream . publish ( Error ( e , "Future.filter" , e . getMessage ) )
2011-08-06 14:03:04 +02:00
Left ( e )
} )
2011-06-18 20:13:13 -06:00
}
2011-07-27 22:20:02 -06:00
}
future
2011-06-18 20:13:13 -06:00
}
2011-02-21 18:28:17 -07:00
2010-11-12 14:04:06 +01:00
/* *
2011-06-16 08:08:31 -07:00
* Returns the current result , throws the exception if one has been raised , else returns None
2010-11-12 14:04:06 +01:00
*/
2011-08-06 14:03:04 +02:00
final def resultOrException : Option [ T ] = value match {
case Some ( Left ( e ) ) ⇒ throw e
case Some ( Right ( r ) ) ⇒ Some ( r )
case _ ⇒ None
2011-02-13 19:59:54 -07:00
}
2011-08-05 08:55:36 -06:00
}
2010-11-12 14:04:06 +01:00
2011-05-03 18:48:42 -06:00
object Promise {
2011-06-17 09:54:49 +02:00
/* *
* Creates a non - completed , new , Promise with the supplied timeout in milliseconds
*/
2011-08-02 10:19:49 -06:00
def apply [ A ] ( timeout : Timeout ) ( implicit dispatcher : MessageDispatcher ) : Promise [ A ] = new DefaultPromise [ A ] ( timeout )
2011-05-03 18:48:42 -06:00
2011-06-17 09:54:49 +02:00
/* *
* Creates a non - completed , new , Promise with the default timeout ( akka . actor . timeout in conf )
*/
2011-10-06 21:19:46 +02:00
def apply [ A ] ( ) ( implicit dispatcher : MessageDispatcher , timeout : Timeout ) : Promise [ A ] = apply ( timeout )
2009-05-25 14:48:43 +02:00
}
2011-03-18 17:37:25 +01:00
/* *
2011-03-30 21:19:26 +02:00
* Essentially this is the Promise ( or write - side ) of a Future ( read - side ) .
2011-03-18 17:37:25 +01:00
*/
2011-05-23 11:31:01 +02:00
trait Promise [ T ] extends Future [ T ] {
2011-03-22 22:12:16 +01:00
/* *
2011-03-30 21:19:26 +02:00
* Completes this Future with the specified result , if not already completed .
* @return this
2011-03-22 22:12:16 +01:00
*/
2011-06-13 22:36:46 +02:00
def complete ( value : Either [ Throwable , T ] ) : this.type
2011-03-22 22:12:16 +01:00
/* *
2011-03-30 21:19:26 +02:00
* Completes this Future with the specified result , if not already completed .
* @return this
2011-03-22 22:12:16 +01:00
*/
2011-06-13 22:36:46 +02:00
final def completeWithResult ( result : T ) : this . type = complete ( Right ( result ) )
2011-03-22 22:12:16 +01:00
/* *
2011-03-30 21:19:26 +02:00
* Completes this Future with the specified exception , if not already completed .
* @return this
2011-03-22 22:12:16 +01:00
*/
2011-06-13 22:36:46 +02:00
final def completeWithException ( exception : Throwable ) : this . type = complete ( Left ( exception ) )
2011-03-22 22:12:16 +01:00
/* *
* Completes this Future with the specified other Future , when that Future is completed ,
2011-03-30 21:19:26 +02:00
* unless this Future has already been completed .
* @return this .
2011-03-22 22:12:16 +01:00
*/
2011-06-13 22:36:46 +02:00
final def completeWith ( other : Future [ T ] ) : this . type = {
2011-05-18 17:25:30 +02:00
other onComplete { f ⇒ complete ( f . value . get ) }
2011-03-16 21:17:38 +01:00
this
2010-11-12 12:52:08 +01:00
}
2011-03-22 22:12:16 +01:00
2011-05-18 17:25:30 +02:00
final def << ( value : T ) : Future [ T ] @cps [ Future [ Any ] ] = shift { cont : ( Future [ T ] ⇒ Future [ Any ] ) ⇒ cont ( complete ( Right ( value ) ) ) }
2011-03-22 22:12:16 +01:00
2011-05-18 17:25:30 +02:00
final def << ( other : Future [ T ] ) : Future [ T ] @cps [ Future [ Any ] ] = shift { cont : ( Future [ T ] ⇒ Future [ Any ] ) ⇒
2011-07-26 22:23:16 -06:00
val fr = new DefaultPromise [ Any ] ( this . timeout )
2011-05-18 17:25:30 +02:00
this completeWith other onComplete { f ⇒
2011-04-23 09:14:20 -06:00
try {
fr completeWith cont ( f )
} catch {
2011-05-18 17:25:30 +02:00
case e : Exception ⇒
2011-11-18 11:59:43 +01:00
dispatcher . prerequisites . eventStream . publish ( Error ( e , "Promise.completeWith" , e . getMessage ) )
2011-04-23 09:14:20 -06:00
fr completeWithException e
}
}
fr
2011-04-21 15:12:47 -06:00
}
2011-03-22 22:12:16 +01:00
2011-05-19 14:43:58 -06:00
final def << ( stream : PromiseStreamOut [ T ] ) : Future [ T ] @cps [ Future [ Any ] ] = shift { cont : ( Future [ T ] ⇒ Future [ Any ] ) ⇒
2011-07-26 22:23:16 -06:00
val fr = new DefaultPromise [ Any ] ( this . timeout )
2011-05-19 14:43:58 -06:00
stream . dequeue ( this ) . onComplete { f ⇒
try {
fr completeWith cont ( f )
} catch {
case e : Exception ⇒
2011-11-18 11:59:43 +01:00
dispatcher . prerequisites . eventStream . publish ( Error ( e , "Promise.completeWith" , e . getMessage ) )
2011-05-19 14:43:58 -06:00
fr completeWithException e
}
}
fr
}
2009-05-25 14:48:43 +02:00
}
2011-08-05 22:27:16 +02:00
//Companion object to FState, just to provide a cheap, immutable default entry
2011-10-29 00:36:42 +02:00
private [ dispatch ] object DefaultPromise {
2011-10-31 22:20:21 +01:00
def EmptyPending [ T ] ( ) : FState [ T ] = emptyPendingValue . asInstanceOf [ FState [ T ] ]
2011-08-05 22:27:16 +02:00
2011-10-12 16:29:33 +02:00
/* *
* Represents the internal state of the DefaultCompletableFuture
*/
sealed trait FState [ + T ] { def value : Option [ Either [ Throwable , T ] ] }
case class Pending [ T ] ( listeners : List [ Future [ T ] ⇒ Unit ] = Nil ) extends FState [ T ] {
def value : Option [ Either [ Throwable , T ] ] = None
}
case class Success [ T ] ( value : Option [ Either [ Throwable , T ] ] = None ) extends FState [ T ] {
def result : T = value . get . right . get
}
case class Failure [ T ] ( value : Option [ Either [ Throwable , T ] ] = None ) extends FState [ T ] {
def exception : Throwable = value . get . left . get
}
case object Expired extends FState [ Nothing ] {
def value : Option [ Either [ Throwable , Nothing ] ] = None
}
2011-10-31 22:20:21 +01:00
private val emptyPendingValue = Pending [ Nothing ] ( Nil )
2011-10-12 16:29:33 +02:00
}
2011-08-05 22:27:16 +02:00
2011-02-28 10:17:44 -07:00
/* *
2011-03-30 21:19:26 +02:00
* The default concrete Future implementation .
2011-02-28 10:17:44 -07:00
*/
2011-10-04 21:17:01 +02:00
class DefaultPromise [ T ] ( val timeout : Timeout ) ( implicit val dispatcher : MessageDispatcher ) extends AbstractPromise with Promise [ T ] {
2011-06-17 06:51:40 -06:00
self ⇒
2010-10-31 19:27:55 +01:00
2011-10-29 00:36:42 +02:00
import DefaultPromise. { FState , Success , Failure , Pending , Expired }
2011-10-13 13:41:44 +02:00
2011-10-06 21:19:46 +02:00
def this ( ) ( implicit dispatcher : MessageDispatcher , timeout : Timeout ) = this ( timeout )
2011-06-18 23:23:47 -06:00
2011-08-02 10:19:49 -06:00
def this ( timeout : Long ) ( implicit dispatcher : MessageDispatcher ) = this ( Timeout ( timeout ) )
2009-06-05 22:08:53 +02:00
2011-08-02 10:19:49 -06:00
def this ( timeout : Long , timeunit : TimeUnit ) ( implicit dispatcher : MessageDispatcher ) = this ( Timeout ( timeout , timeunit ) )
2011-02-12 12:26:56 -07:00
2009-05-25 14:48:43 +02:00
private val _startTimeInNanos = currentTimeInNanos
2009-06-21 14:08:43 +02:00
2011-02-12 12:26:56 -07:00
@tailrec
2011-04-27 15:34:42 +02:00
private def awaitUnsafe ( waitTimeNanos : Long ) : Boolean = {
2011-08-05 22:27:16 +02:00
if ( value . isEmpty && waitTimeNanos > 0 ) {
2011-12-02 17:13:46 +01:00
val ms = NANOSECONDS . toMillis ( waitTimeNanos )
2011-08-05 22:27:16 +02:00
val ns = ( waitTimeNanos % 1000000 l ) . toInt //As per object.wait spec
2011-02-07 18:59:49 +01:00
val start = currentTimeInNanos
2011-10-04 21:17:01 +02:00
try { synchronized { if ( value . isEmpty ) wait ( ms , ns ) } } catch { case e : InterruptedException ⇒ }
2011-08-05 22:27:16 +02:00
2011-08-06 20:44:49 +02:00
awaitUnsafe ( waitTimeNanos - ( currentTimeInNanos - start ) )
2011-02-12 09:16:29 -07:00
} else {
2011-08-05 22:27:16 +02:00
value . isDefined
2011-02-07 18:59:49 +01:00
}
2011-02-12 09:16:29 -07:00
}
2011-10-27 20:04:32 -06:00
def await ( atMost : Duration ) : this . type = if ( value . isDefined ) this else {
2011-11-05 12:48:19 -06:00
Future . blocking ( )
2011-10-27 20:04:32 -06:00
2011-08-06 20:05:43 +02:00
val waitNanos =
if ( timeout . duration . isFinite && atMost . isFinite )
atMost . toNanos min timeLeft ( )
else if ( atMost . isFinite )
atMost . toNanos
else if ( timeout . duration . isFinite )
timeLeft ( )
else Long . MaxValue //If both are infinite, use Long.MaxValue
2011-08-05 22:27:16 +02:00
if ( awaitUnsafe ( waitNanos ) ) this
2011-12-02 17:13:46 +01:00
else throw new FutureTimeoutException ( "Futures timed out after [" + NANOSECONDS . toMillis ( waitNanos ) + "] milliseconds" )
2009-05-25 14:48:43 +02:00
}
2011-08-01 12:33:40 +02:00
def await = await ( timeout . duration )
2011-06-18 23:23:47 -06:00
def isExpired : Boolean = if ( timeout . duration . isFinite ) timeLeft ( ) <= 0 else false
2009-05-25 14:48:43 +02:00
2011-10-04 21:17:01 +02:00
def value : Option [ Either [ Throwable , T ] ] = getState . value
@inline
protected final def updateState ( oldState : FState [ T ] , newState : FState [ T ] ) : Boolean =
AbstractPromise . updater . asInstanceOf [ AtomicReferenceFieldUpdater [ AbstractPromise , FState [ T ] ] ] . compareAndSet ( this , oldState , newState )
@inline
2011-10-12 16:29:33 +02:00
protected final def getState : FState [ T ] = {
@tailrec
def read ( ) : FState [ T ] = {
val cur = AbstractPromise . updater . asInstanceOf [ AtomicReferenceFieldUpdater [ AbstractPromise , FState [ T ] ] ] . get ( this )
if ( cur . isInstanceOf [ Pending [ _ ] ] && isExpired ) {
if ( updateState ( cur , Expired ) ) Expired else read ( )
} else cur
}
read ( )
}
2010-11-12 12:11:53 +01:00
2011-06-13 22:36:46 +02:00
def complete ( value : Either [ Throwable , T ] ) : this . type = {
2011-08-05 08:55:36 -06:00
val callbacks = {
2011-07-28 09:57:45 -06:00
try {
2011-08-05 22:27:16 +02:00
@tailrec
def tryComplete : List [ Future [ T ] ⇒ Unit ] = {
2011-10-04 21:17:01 +02:00
val cur = getState
2011-10-12 16:29:33 +02:00
cur match {
case Pending ( listeners ) ⇒
if ( updateState ( cur , if ( value . isLeft ) Failure ( Some ( value ) ) else Success ( Some ( value ) ) ) ) listeners
else tryComplete
case _ ⇒ Nil
2011-07-28 09:57:45 -06:00
}
2011-04-29 13:22:39 +02:00
}
2011-08-05 22:27:16 +02:00
tryComplete
2011-07-28 09:57:45 -06:00
} finally {
2011-10-04 21:17:01 +02:00
synchronized { notifyAll ( ) } //Notify any evil blockers
2011-04-28 20:53:45 -06:00
}
}
2011-02-28 10:17:44 -07:00
2011-08-05 08:55:36 -06:00
if ( callbacks . nonEmpty ) Future . dispatchTask ( ( ) ⇒ callbacks foreach notifyCompleted )
2011-04-28 21:14:18 -06:00
2011-02-08 16:14:40 +01:00
this
2010-11-12 12:11:53 +01:00
}
2011-06-13 22:36:46 +02:00
def onComplete ( func : Future [ T ] ⇒ Unit ) : this . type = {
2011-08-05 22:27:16 +02:00
@tailrec //Returns whether the future has already been completed or not
def tryAddCallback ( ) : Boolean = {
2011-10-04 21:17:01 +02:00
val cur = getState
2011-10-12 16:29:33 +02:00
cur match {
case _ : Success [ _ ] | _ : Failure [ _ ] ⇒ true
case Expired ⇒ false
case p : Pending [ _ ] ⇒
val pt = p . asInstanceOf [ Pending [ T ] ]
if ( updateState ( pt , pt . copy ( listeners = func : : pt . listeners ) ) ) false
else tryAddCallback ( )
}
2011-02-28 10:17:44 -07:00
}
2011-08-06 14:03:04 +02:00
if ( tryAddCallback ( ) ) Future . dispatchTask ( ( ) ⇒ notifyCompleted ( func ) )
2011-02-28 10:17:44 -07:00
2010-11-12 12:11:53 +01:00
this
2009-05-25 14:48:43 +02:00
}
2011-06-17 06:51:40 -06:00
def onTimeout ( func : Future [ T ] ⇒ Unit ) : this . type = {
2011-08-05 22:27:16 +02:00
val runNow =
if ( ! timeout . duration . isFinite ) false //Not possible
else if ( value . isEmpty ) {
if ( ! isExpired ) {
2011-08-06 14:10:36 -06:00
val runnable = new Runnable {
def run ( ) {
if ( ! isCompleted ) {
2011-12-03 21:26:32 +01:00
if ( ! isExpired )
2011-12-05 22:46:34 +01:00
try dispatcher . prerequisites . scheduler . scheduleOnce ( Duration ( timeLeftNoinline ( ) , TimeUnit . NANOSECONDS ) , this )
2011-12-03 21:26:32 +01:00
catch {
case _ : IllegalStateException ⇒ func ( DefaultPromise . this )
}
2011-08-06 14:10:36 -06:00
else func ( DefaultPromise . this )
2011-06-18 23:23:47 -06:00
}
2011-06-17 06:51:40 -06:00
}
2011-08-06 14:10:36 -06:00
}
2011-12-02 17:13:46 +01:00
val timeoutFuture = dispatcher . prerequisites . scheduler . scheduleOnce ( Duration ( timeLeft ( ) , NANOSECONDS ) , runnable )
2011-11-09 15:25:14 +01:00
onComplete ( _ ⇒ timeoutFuture . cancel ( ) )
2011-08-05 22:27:16 +02:00
false
} else true
} else false
2011-06-17 06:51:40 -06:00
2011-08-05 22:27:16 +02:00
if ( runNow ) Future . dispatchTask ( ( ) ⇒ notifyCompleted ( func ) )
2011-06-17 06:51:40 -06:00
this
}
2011-06-20 16:22:46 -06:00
final def orElse [ A >: T ] ( fallback : ⇒ A ) : Future [ A ] =
if ( timeout . duration . isFinite ) {
2011-10-12 16:29:33 +02:00
getState match {
case _ : Success [ _ ] | _ : Failure [ _ ] ⇒ this
2011-10-13 13:41:44 +02:00
case Expired ⇒ Future [ A ] ( fallback , timeout )
2011-10-12 16:29:33 +02:00
case _ : Pending [ _ ] ⇒
2011-08-06 20:44:49 +02:00
val promise = new DefaultPromise [ A ] ( Timeout . never ) //TODO FIXME We can't have infinite timeout here, doesn't make sense.
2011-06-20 16:22:46 -06:00
promise completeWith this
val runnable = new Runnable {
def run ( ) {
2011-08-06 14:10:36 -06:00
if ( ! isCompleted ) {
2011-12-03 21:26:32 +01:00
val done =
if ( ! isExpired )
try {
2011-12-05 22:46:34 +01:00
dispatcher . prerequisites . scheduler . scheduleOnce ( Duration ( timeLeftNoinline ( ) , TimeUnit . NANOSECONDS ) , this )
2011-12-03 21:26:32 +01:00
true
} catch {
case _ : IllegalStateException ⇒ false
}
else false
if ( ! done )
promise complete ( try { Right ( fallback ) } catch { case e ⇒ Left ( e ) } ) // FIXME catching all and continue isn't good for OOME, ticket #1418
2011-08-06 14:10:36 -06:00
}
2011-06-20 16:22:46 -06:00
}
}
2011-12-02 17:13:46 +01:00
dispatcher . prerequisites . scheduler . scheduleOnce ( Duration ( timeLeft ( ) , NANOSECONDS ) , runnable )
2011-06-20 16:22:46 -06:00
promise
}
} else this
2011-05-18 17:25:30 +02:00
private def notifyCompleted ( func : Future [ T ] ⇒ Unit ) {
2011-11-30 10:20:57 +01:00
// FIXME catching all and continue isn't good for OOME, ticket #1418
2011-11-18 11:59:43 +01:00
try { func ( this ) } catch { case e ⇒ dispatcher . prerequisites . eventStream . publish ( Error ( e , "Future" , "Future onComplete-callback raised an exception" ) ) } //TODO catch, everything? Really?
2010-11-12 12:11:53 +01:00
}
2010-10-31 19:27:55 +01:00
2011-05-18 17:25:30 +02:00
@inline
2011-12-02 17:13:46 +01:00
private def currentTimeInNanos : Long = MILLISECONDS . toNanos ( System . currentTimeMillis ) //TODO Switch to math.abs(System.nanoTime)?
2011-08-13 08:27:10 +03:00
//TODO: the danger of Math.abs is that it could break the ordering of time. So I would not recommend an abs.
2011-05-18 17:25:30 +02:00
@inline
private def timeLeft ( ) : Long = timeoutInNanos - ( currentTimeInNanos - _startTimeInNanos )
2011-09-03 12:06:52 +02:00
private def timeLeftNoinline ( ) : Long = timeLeft ( )
2009-05-25 14:48:43 +02:00
}
2011-03-18 17:26:53 +01:00
2011-03-18 17:37:25 +01:00
/* *
* An already completed Future is seeded with it 's result at creation , is useful for when you are participating in
* a Future - composition but you already have a value to contribute .
*/
2011-08-02 10:19:49 -06:00
sealed class KeptPromise [ T ] ( suppliedValue : Either [ Throwable , T ] ) ( implicit val dispatcher : MessageDispatcher ) extends Promise [ T ] {
2011-03-18 17:26:53 +01:00
val value = Some ( suppliedValue )
2011-06-13 22:36:46 +02:00
def complete ( value : Either [ Throwable , T ] ) : this . type = this
2011-08-02 10:19:49 -06:00
def onComplete ( func : Future [ T ] ⇒ Unit ) : this . type = {
2011-08-05 08:55:36 -06:00
Future dispatchTask ( ( ) ⇒ func ( this ) )
2011-07-28 10:10:41 -06:00
this
}
2011-06-13 22:36:46 +02:00
def await ( atMost : Duration ) : this . type = this
def await : this . type = this
2011-03-22 14:45:31 +01:00
def isExpired : Boolean = true
2011-06-18 23:23:47 -06:00
def timeout : Timeout = Timeout . zero
2011-05-19 14:37:54 -06:00
2011-06-17 06:51:40 -06:00
final def onTimeout ( func : Future [ T ] ⇒ Unit ) : this . type = this
2011-06-20 16:22:46 -06:00
final def orElse [ A >: T ] ( fallback : ⇒ A ) : Future [ A ] = this
2011-06-17 06:51:40 -06:00
2011-03-18 17:26:53 +01:00
}