diff options
author | Jason Zaugg <jzaugg@gmail.com> | 2013-07-07 10:48:11 +1000 |
---|---|---|
committer | Jason Zaugg <jzaugg@gmail.com> | 2013-07-07 10:48:11 +1000 |
commit | 2d8506a64392cd7192b6831c38798cc9a7c8bfed (patch) | |
tree | 84eafcf1a9a179eeaa97dd1e3595c18351b2b814 /src/main/scala/scala/async/internal/FutureSystem.scala | |
parent | c60c38ca6098402f7a9cc6d6746b664bb2b1306c (diff) | |
download | scala-async-2d8506a64392cd7192b6831c38798cc9a7c8bfed.tar.gz scala-async-2d8506a64392cd7192b6831c38798cc9a7c8bfed.tar.bz2 scala-async-2d8506a64392cd7192b6831c38798cc9a7c8bfed.zip |
Move implementation details to scala.async.internal._.
If we intend to keep CPS fallback around for any length of time
it should probably move there too.
Diffstat (limited to 'src/main/scala/scala/async/internal/FutureSystem.scala')
-rw-r--r-- | src/main/scala/scala/async/internal/FutureSystem.scala | 106 |
1 files changed, 106 insertions, 0 deletions
diff --git a/src/main/scala/scala/async/internal/FutureSystem.scala b/src/main/scala/scala/async/internal/FutureSystem.scala new file mode 100644 index 0000000..101b7bf --- /dev/null +++ b/src/main/scala/scala/async/internal/FutureSystem.scala @@ -0,0 +1,106 @@ +/* + * Copyright (C) 2012 Typesafe Inc. <http://www.typesafe.com> + */ +package scala.async.internal + +import scala.language.higherKinds + +import scala.reflect.macros.Context +import scala.reflect.internal.SymbolTable + +/** + * An abstraction over a future system. + * + * Used by the macro implementations in [[scala.async.AsyncBase]] to + * customize the code generation. + * + * The API mirrors that of `scala.concurrent.Future`, see the instance + * [[ScalaConcurrentFutureSystem]] for an example of how + * to implement this. + */ +trait FutureSystem { + /** A container to receive the final value of the computation */ + type Prom[A] + /** A (potentially in-progress) computation */ + type Fut[A] + /** An execution context, required to create or register an on completion callback on a Future. */ + type ExecContext + + trait Ops { + val universe: reflect.internal.SymbolTable + + import universe._ + def Expr[T: WeakTypeTag](tree: Tree): Expr[T] = universe.Expr[T](rootMirror, universe.FixedMirrorTreeCreator(rootMirror, tree)) + + def promType[A: WeakTypeTag]: Type + def execContextType: Type + + /** Create an empty promise */ + def createProm[A: WeakTypeTag]: Expr[Prom[A]] + + /** Extract a future from the given promise. */ + def promiseToFuture[A: WeakTypeTag](prom: Expr[Prom[A]]): Expr[Fut[A]] + + /** Construct a future to asynchronously compute the given expression */ + def future[A: WeakTypeTag](a: Expr[A])(execContext: Expr[ExecContext]): Expr[Fut[A]] + + /** Register an call back to run on completion of the given future */ + def onComplete[A, U](future: Expr[Fut[A]], fun: Expr[scala.util.Try[A] => U], + execContext: Expr[ExecContext]): Expr[Unit] + + /** Complete a promise with a value */ + def completeProm[A](prom: Expr[Prom[A]], value: Expr[scala.util.Try[A]]): Expr[Unit] + + def spawn(tree: Tree, execContext: Tree): Tree = + future(Expr[Unit](tree))(Expr[ExecContext](execContext)).tree + + // TODO Why is this needed? + def castTo[A: WeakTypeTag](future: Expr[Fut[Any]]): Expr[Fut[A]] + } + + def mkOps(c: SymbolTable): Ops { val universe: c.type } +} + +object ScalaConcurrentFutureSystem extends FutureSystem { + + import scala.concurrent._ + + type Prom[A] = Promise[A] + type Fut[A] = Future[A] + type ExecContext = ExecutionContext + + def mkOps(c: SymbolTable): Ops {val universe: c.type} = new Ops { + val universe: c.type = c + + import universe._ + + def promType[A: WeakTypeTag]: Type = weakTypeOf[Promise[A]] + def execContextType: Type = weakTypeOf[ExecutionContext] + + def createProm[A: WeakTypeTag]: Expr[Prom[A]] = reify { + Promise[A]() + } + + def promiseToFuture[A: WeakTypeTag](prom: Expr[Prom[A]]) = reify { + prom.splice.future + } + + def future[A: WeakTypeTag](a: Expr[A])(execContext: Expr[ExecContext]) = reify { + Future(a.splice)(execContext.splice) + } + + def onComplete[A, U](future: Expr[Fut[A]], fun: Expr[scala.util.Try[A] => U], + execContext: Expr[ExecContext]): Expr[Unit] = reify { + future.splice.onComplete(fun.splice)(execContext.splice) + } + + def completeProm[A](prom: Expr[Prom[A]], value: Expr[scala.util.Try[A]]): Expr[Unit] = reify { + prom.splice.complete(value.splice) + Expr[Unit](Literal(Constant(()))).splice + } + + def castTo[A: WeakTypeTag](future: Expr[Fut[Any]]): Expr[Fut[A]] = reify { + future.splice.asInstanceOf[Fut[A]] + } + } +} |