might have a workable solution to stack overflow
This commit is contained in:
parent
9d91990135
commit
4967c8cb72
3 changed files with 44 additions and 40 deletions
|
|
@ -624,7 +624,9 @@ class FutureSpec extends JUnitSuite {
|
|||
import Future.flow
|
||||
import akka.util.cps._
|
||||
|
||||
val promises = List.fill(1000)(Promise[Int]())
|
||||
val count = 10000
|
||||
|
||||
val promises = List.fill(count)(Promise[Int]())
|
||||
|
||||
flow {
|
||||
var i = 0
|
||||
|
|
@ -641,7 +643,7 @@ class FutureSpec extends JUnitSuite {
|
|||
i += 1
|
||||
}
|
||||
|
||||
assert(i === 1000)
|
||||
assert(i === count)
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,13 +0,0 @@
|
|||
package akka.util.cps
|
||||
|
||||
import scala.util.continuations._
|
||||
|
||||
object TailCalls {
|
||||
sealed trait TailRec[A, B]
|
||||
case class Return[A, B](result: A) extends TailRec[A, B]
|
||||
case class Call[A, B](thunk: () ⇒ TailRec[A, B] @cps[B]) extends TailRec[A, B]
|
||||
def tailcall[A, B](comp: TailRec[A, B]): A @cps[B] = comp match {
|
||||
case Call(thunk) ⇒ tailcall(thunk())
|
||||
case Return(x) ⇒ x
|
||||
}
|
||||
}
|
||||
|
|
@ -5,36 +5,51 @@ import scala.util.continuations._
|
|||
package object cps {
|
||||
def matchC[A, B, C, D](in: A)(pf: PartialFunction[A, B @cpsParam[C, D]]): B @cpsParam[C, D] = pf(in)
|
||||
|
||||
import TailCalls._
|
||||
|
||||
def loopC[A](block: ⇒ Any @cps[A]): Unit @cps[A] = {
|
||||
def f(): TailRec[Unit, A] @cps[A] = {
|
||||
block
|
||||
Call(() ⇒ f())
|
||||
}
|
||||
tailcall[Unit, A](f())
|
||||
block
|
||||
loopC(block)
|
||||
}
|
||||
|
||||
def whileC[A](test: ⇒ Boolean)(block: ⇒ Any @cps[A]): Unit @cps[A] = {
|
||||
def f(): TailRec[Unit, A] @cps[A] = {
|
||||
if (test) {
|
||||
block
|
||||
Call(() ⇒ f())
|
||||
} else shiftUnit(Return(()))
|
||||
}
|
||||
tailcall[Unit, A](f())
|
||||
}
|
||||
def whileC[A](test: ⇒ Boolean)(block: ⇒ Unit @cps[A])(implicit loop: CPSLoop[A]): Unit @cps[A] =
|
||||
loop.whileC(test)(block)
|
||||
|
||||
def repeatC[A](times: Int)(block: ⇒ Any @cps[A]): Unit @cps[A] = {
|
||||
var i = 0
|
||||
def f(): TailRec[Unit, A] @cps[A] = {
|
||||
if (i < times) {
|
||||
i += 1
|
||||
block
|
||||
Call(() ⇒ f())
|
||||
} else shiftUnit(Return(()))
|
||||
if (times > 0) {
|
||||
block
|
||||
repeatC(times - 1)(block)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
package cps {
|
||||
object CPSLoop extends DefaultCPSLoop {
|
||||
import akka.dispatch.{ Future, Promise }
|
||||
|
||||
implicit val futureCPSLoop: CPSLoop[Future[Any]] = new CPSLoop[Future[Any]] {
|
||||
def whileC(test: ⇒ Boolean)(block: ⇒ Unit @cps[Future[Any]]): Unit @cps[Future[Any]] = {
|
||||
shift { c: (Unit ⇒ Future[Any]) ⇒
|
||||
Future.flow {
|
||||
if (test) {
|
||||
block
|
||||
Future(()).apply
|
||||
whileC(test)(block)
|
||||
}
|
||||
} flatMap c
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
trait CPSLoop[A] {
|
||||
def whileC(test: ⇒ Boolean)(block: ⇒ Unit @cps[A]): Unit @cps[A]
|
||||
}
|
||||
trait DefaultCPSLoop {
|
||||
implicit val defaultCPSLoop = new CPSLoop[Any] {
|
||||
def whileC(test: ⇒ Boolean)(block: ⇒ Unit @cps[Any]): Unit @cps[Any] = {
|
||||
if (test) {
|
||||
block
|
||||
whileC(test)(block)
|
||||
}
|
||||
}
|
||||
}
|
||||
tailcall[Unit, A](f())
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue