This page is no longer maintained — Please continue to the home page at www.scala-lang.org

Actors: Creating a continuation context

19 replies
Sciss
Joined: 2008-12-17,
User offline. Last seen 28 weeks 5 days ago.

hi,

continuing my "Again: using actors to schedule things in time"
thread, i have read the latest paper by phillip haller and refreshed
my knowledge of the internals of the actors library. i understand the
way an actor is detached and the way the continuation is stored in
react. but to have ugly andThen chains is really a pity. what i would
like to write is:

routine {
var count = 0;
println( "Entering routine loop" )
while( count < 10 ) {
println( "Here! " + count + "; " +
Thread.currentThread.hashCode )
count = count + 1
sleep( 666 )
}
println( "Kuuka" )
sleep( 2000 )
println( "Finally" )
}

and currently i can get the behaviour using this code:

import scala.actors.Actor
import scala.actors.Actor._
import scala.collection.mutable.PriorityQueue

case class Reschedule( delta: Long, who: Actor )
case class Awake
case class Scheduled( when: Long, what: Actor ) extends Ordered
[Scheduled] {
def compare( that: Scheduled ) = when.compare( that.when )
}

object Main extends Application {
var verbose = true
var sched : MyScheduler = _

/**
* @param args the command line arguments
*/
override def main(args: Array[String]) = {
sched = new MyScheduler
sched.start
routine {
var count = 0;
println( "Entering routine loop" )
loopWhile( count < 10 ) {
println( "Here! " + count + "; " +
Thread.currentThread.hashCode )
count = count + 1
sleep( 666 )
} andThen {
println( "Kuuka" )
sleep( 2000 ) andThen {
println( "Finally" )
}
}
}
}

def routine( body: => Unit ) {
val actor = new Actor {
def act {
sleep( 0 ) andThen body
}
}
actor.start
actor
}

def sleep( delta: Long ) {
sched ! Reschedule( delta, Actor.self )
react { case Awake => if( verbose ) println( "Awoken" )}
}
}

class MyScheduler extends Actor {
var verbose = true

private val queue = new PriorityQueue[Scheduled]
def act {
loop {
val now = System.currentTimeMillis
if( verbose ) {
println( "Entering react at " + now + " ; " +
Thread.currentThread.hashCode )
}
react {
case r: Reschedule => {
if( verbose ) {
println( "Received reschedule " + r.delta )
}
queue += Scheduled( now + Math.max( 0,
r.delta ), r.who )
while( !queue.isEmpty ) {
val x = queue.dequeue
if( verbose ) {
println( "Dequeued " + x.when )
}
if( x.when > now ) {
if( verbose ) {
println( "Sleeping for " + (x.when -
now) )
}
Thread.sleep( x.when - now )
}
if( verbose ) {
println( "Awaking actor : " + r.who )
}
x.what ! Awake
}
if( verbose ) println( "Queue done" )
}

case _ => {
println( "Wooooo" )
}
}
}
}
}

now my question is: are there no other means to get a proper
continuation than passing in a PartialFunction to andThen? in other
words, if i had a block

{
println( "A" )
sleep( 666 )
println( "B" )
}

isn't there a way to implement the sleep method that it can determine
the current execution context / continuation, and then throught the
SuspendActorException, so that execution is resumed with println
( "B" ).... ? is there any way to hide the andThen chains and the
necessity to nest functions inside functions?

thanks for help! ciao, -sciss-

Alex Boisvert
Joined: 2008-12-16,
User offline. Last seen 42 years 45 weeks ago.
Re: Actors: Creating a continuation context
On Thu, Feb 12, 2009 at 5:54 PM, Sciss <contact@sciss.de> wrote:
isn't there a way to implement the sleep method that it can determine the current execution context / continuation, and then throught the SuspendActorException, so that execution is resumed with println( "B" ).... ? is there any way to hide the andThen chains and the necessity to nest functions inside functions?

Short answer:  It's difficult and typically fragile.

The current actor framework is not based on real continuations but on closures.

There are a few projects trying to implement real/better continuations for Java: Javaflow, Kilim, and I know I'm forgetting a couple of others... 

alex

Sciss
Joined: 2008-12-17,
User offline. Last seen 28 weeks 5 days ago.
Re: Actors: Creating a continuation context

so there is no way getting around this except using java bytecode
weavers? ;-(

Am 13.02.2009 um 03:01 schrieb Alex Boisvert:

> On Thu, Feb 12, 2009 at 5:54 PM, Sciss wrote:
> isn't there a way to implement the sleep method that it can
> determine the current execution context / continuation, and then
> throught the SuspendActorException, so that execution is resumed
> with println( "B" ).... ? is there any way to hide the andThen
> chains and the necessity to nest functions inside functions?
>
> Short answer: It's difficult and typically fragile.
>
> The current actor framework is not based on real continuations but
> on closures.
>
> There are a few projects trying to implement real/better
> continuations for Java: Javaflow, Kilim, and I know I'm forgetting
> a couple of others...
>
> alex
>

Alex Boisvert
Joined: 2008-12-16,
User offline. Last seen 42 years 45 weeks ago.
Re: Actors: Creating a continuation context
On Thu, Feb 12, 2009 at 6:06 PM, Sciss <contact@sciss.de> wrote:
so there is no way getting around this except using java bytecode weavers?  ;-(

or native jvm support... pick your poison ;)

Rich Dougherty 2
Joined: 2009-01-19,
User offline. Last seen 42 years 45 weeks ago.
Re: Actors: Creating a continuation context

On Fri, Feb 13, 2009 at 2:54 PM, Sciss wrote:
> isn't there a way to implement the sleep method that it can determine the
> current execution context / continuation, and then throught the
> SuspendActorException, so that execution is resumed with println( "B" )....
> ? is there any way to hide the andThen chains and the necessity to nest
> functions inside functions?

There's no automatic way you can do it, but you can avoid andThen and
nesting by using a for loop's syntactic sugar. See for example
Responder.

http://scala.sygneca.com/libs/responder
http://www.scala-lang.org/docu/files/api/scala/Responder.html

I have done a similar thing for linking together asynchronous
operations (like react). Below is an example that uses react to get
two numbers, then sends the result to another actor. The functions
"areact" and "async0" create AsyncFunctions - functions that return
their result asynchronously. These are joined together by the for loop
into a big AsyncFunction. The whole thing is then executed with the
"->" operator and the result sent to the continuation created by the
"fc0" method.

(for (
x <- areact { case i: Int => i };
_ <- async0 { println("Received " + x) };
y <- areact { case i: Int => i };
_ <- async0 { println("Received " + y) };
_ <- async0 { caller ! (x + y) })
yield ()) -> fc0(())(thrower)

Here's your sleep example, written another way:

(for (
_ <- async0 { println("A") };
_ <- asleep(666);
_ <- async0 { println("B") })
yield ()).toFunction.apply

In this case, instead of sending the result to a continuation with the
"->" operator, I convert the AsyncFunction into a synchronous
Function0, and apply it directly.

The for loop syntax is not pretty - I don't know if it's much better
than using andThen! But if you're interested, you can see the
implementation of AsyncFunctions in the "controlflow" module of Scala
OTP.

http://github.com/richdougherty/scala-otp

Cheers
Rich

--
http://www.richdougherty.com/

Sciss
Joined: 2008-12-17,
User offline. Last seen 28 weeks 5 days ago.
Re: Actors: Creating a continuation context

ok, thanks for the example. but isn't react particularly synchronous,
"detaching" the actor instead of "suspending" it, and not asynchronous?

i am in fact looking for a synchronous thing, to create cooperative
multitasking (coroutines).

i'm looking into kilim in this moment, see if i can get it to weave
on top of my scala bytecode. the performance seems interesting, and
the author mentions somewhere that it would be easy to write a custom
scheduler to allow logical time advancing, which is exactly what i'm
looking after....

cheers, -sciss-

Am 13.02.2009 um 12:07 schrieb Rich Dougherty:

> On Fri, Feb 13, 2009 at 2:54 PM, Sciss wrote:
>> isn't there a way to implement the sleep method that it can
>> determine the
>> current execution context / continuation, and then throught the
>> SuspendActorException, so that execution is resumed with println
>> ( "B" )....
>> ? is there any way to hide the andThen chains and the necessity to
>> nest
>> functions inside functions?
>
> There's no automatic way you can do it, but you can avoid andThen and
> nesting by using a for loop's syntactic sugar. See for example
> Responder.
>
> http://scala.sygneca.com/libs/responder
> http://www.scala-lang.org/docu/files/api/scala/Responder.html
>
> I have done a similar thing for linking together asynchronous
> operations (like react). Below is an example that uses react to get
> two numbers, then sends the result to another actor. The functions
> "areact" and "async0" create AsyncFunctions - functions that return
> their result asynchronously. These are joined together by the for loop
> into a big AsyncFunction. The whole thing is then executed with the
> "->" operator and the result sent to the continuation created by the
> "fc0" method.
>
> (for (
> x <- areact { case i: Int => i };
> _ <- async0 { println("Received " + x) };
> y <- areact { case i: Int => i };
> _ <- async0 { println("Received " + y) };
> _ <- async0 { caller ! (x + y) })
> yield ()) -> fc0(())(thrower)
>
> Here's your sleep example, written another way:
>
> (for (
> _ <- async0 { println("A") };
> _ <- asleep(666);
> _ <- async0 { println("B") })
> yield ()).toFunction.apply
>
> In this case, instead of sending the result to a continuation with the
> "->" operator, I convert the AsyncFunction into a synchronous
> Function0, and apply it directly.
>
> The for loop syntax is not pretty - I don't know if it's much better
> than using andThen! But if you're interested, you can see the
> implementation of AsyncFunctions in the "controlflow" module of Scala
> OTP.
>
> http://github.com/richdougherty/scala-otp
>
> Cheers
> Rich
>
> --
> http://www.richdougherty.com/

Rich Dougherty 2
Joined: 2009-01-19,
User offline. Last seen 42 years 45 weeks ago.
Re: Actors: Creating a continuation context

On Sat, Feb 14, 2009 at 1:08 AM, Sciss wrote:
> ok, thanks for the example. but isn't react particularly synchronous,
> "detaching" the actor instead of "suspending" it, and not asynchronous?
>
> i am in fact looking for a synchronous thing, to create cooperative
> multitasking (coroutines).

Well, it probably depends on your definition of "synchronous" and
"asynchronous", but I think I get your point. If you want to truly
suspend the computation - which requires true continuations - then
that's not what's happening here.

> i'm looking into kilim in this moment, see if i can get it to weave on top
> of my scala bytecode. the performance seems interesting, and the author
> mentions somewhere that it would be easy to write a custom scheduler to
> allow logical time advancing, which is exactly what i'm looking after....

Kilim looks interesting. It would be fantastic if the JVM supported
continuations natively...

Rich

--
http://www.richdougherty.com/

Philipp Haller
Joined: 2009-01-13,
User offline. Last seen 42 years 45 weeks ago.
Re: Actors: Creating a continuation context

Hi,

There is another possibility using a Scala compiler plugin for delimited
continuations created by Tiark Rompf. Currently, it lives in the Scala
SVN under

http://lampsvn.epfl.ch/trac/scala/browser/compiler-plugins/continuations...

Using this plugin your actor code can be written as follows (sleeping
code simplified):

object Sleep {
import ActorUtils._

def sleep(delta: Long): Unit @suspendable = {
self ! 'Awake
proceed (react) { case 'Awake => println("Awoken") }
}

def main(args: Array[String]) {
actor {
reset {
println("A")
sleep(1000)
println("B")
}
}
}
}

Note that I have put a `reset` around the block that contains the
invocation of `sleep`. This defines the boundaries of the continuation
context that you are saving inside `sleep` (or any other method that
captures the current continuation).

The actual continuation is captured by `proceed` which is called inside
`sleep. It is used to extend the closure saved by `react` with the
current continuation up to the next enclosing `reset`. Note that all
code that uses continuation-capturing methods must be `@suspendable`,
i.e. transformed by the compiler plugin.

The `proceed` utility function is defined in the `ActorUtils` object:

object ActorUtils {
def proceed[A, B](fun: PartialFunction[A, Unit] => Nothing):
PartialFunction[A, B] => B @cps[Unit, Unit] =
(caseBlock: PartialFunction[A, B]) =>
shift[B, Unit, Unit]((k: B => Unit) => fun(caseBlock andThen k))
}

Basically, what this function does is it takes a closure-saving
function, such as `react`, and turns it into a function that takes a
block of cases (`caseBlock`), just like `react`, except that `caseBlock`
has a result type `B`, since we can continue processing a value of that
type. `shift` captures the current continuation, and invokes its
argument function with it. In this case we call the original
closure-saving function (`react`), but with a closure that is extended
with the continuation (we pass the continuation into `react`).

The performance of this approach should be comparable to Kilim. However,
keep in mind that Scala's actors have many more features than Kilim
(such as message pattern matching, `Actor.self`, implicit sender ID,
threads interop, and actor links) which currently lead to a certain
overhead. It is not easy to implement these features without paying for it.
I am not sure whether Kilim uses Lea's FJTask framework like Scala's
actors. It is faster than using a standard Java 5 executor, since it
avoids a central queue for incoming tasks.

Cheers,
Philipp

Sciss wrote:
> ok, thanks for the example. but isn't react particularly synchronous,
> "detaching" the actor instead of "suspending" it, and not asynchronous?
>
> i am in fact looking for a synchronous thing, to create cooperative
> multitasking (coroutines).
>
> i'm looking into kilim in this moment, see if i can get it to weave
> on top of my scala bytecode. the performance seems interesting, and
> the author mentions somewhere that it would be easy to write a custom
> scheduler to allow logical time advancing, which is exactly what i'm
> looking after....
>
> cheers, -sciss-
>
>
> Am 13.02.2009 um 12:07 schrieb Rich Dougherty:
>
>> On Fri, Feb 13, 2009 at 2:54 PM, Sciss wrote:
>>> isn't there a way to implement the sleep method that it can
>>> determine the
>>> current execution context / continuation, and then throught the
>>> SuspendActorException, so that execution is resumed with println
>>> ( "B" )....
>>> ? is there any way to hide the andThen chains and the necessity to
>>> nest
>>> functions inside functions?
>> There's no automatic way you can do it, but you can avoid andThen and
>> nesting by using a for loop's syntactic sugar. See for example
>> Responder.
>>
>> http://scala.sygneca.com/libs/responder
>> http://www.scala-lang.org/docu/files/api/scala/Responder.html
>>
>> I have done a similar thing for linking together asynchronous
>> operations (like react). Below is an example that uses react to get
>> two numbers, then sends the result to another actor. The functions
>> "areact" and "async0" create AsyncFunctions - functions that return
>> their result asynchronously. These are joined together by the for loop
>> into a big AsyncFunction. The whole thing is then executed with the
>> "->" operator and the result sent to the continuation created by the
>> "fc0" method.
>>
>> (for (
>> x <- areact { case i: Int => i };
>> _ <- async0 { println("Received " + x) };
>> y <- areact { case i: Int => i };
>> _ <- async0 { println("Received " + y) };
>> _ <- async0 { caller ! (x + y) })
>> yield ()) -> fc0(())(thrower)
>>
>> Here's your sleep example, written another way:
>>
>> (for (
>> _ <- async0 { println("A") };
>> _ <- asleep(666);
>> _ <- async0 { println("B") })
>> yield ()).toFunction.apply
>>
>> In this case, instead of sending the result to a continuation with the
>> "->" operator, I convert the AsyncFunction into a synchronous
>> Function0, and apply it directly.
>>
>> The for loop syntax is not pretty - I don't know if it's much better
>> than using andThen! But if you're interested, you can see the
>> implementation of AsyncFunctions in the "controlflow" module of Scala
>> OTP.
>>
>> http://github.com/richdougherty/scala-otp
>>
>> Cheers
>> Rich
>>
>> --
>> http://www.richdougherty.com/
>

StephaneLD
Joined: 2008-08-28,
User offline. Last seen 4 years 9 weeks ago.
Re: Actors: Creating a continuation context
Speaking of Compiler plugins..Will some of them will be part of the standard distribution?How will that play with IDE using the compiler?Thanks for any pointers..Stephane

On Mon, Feb 16, 2009 at 3:36 PM, Philipp Haller <philipp.haller@epfl.ch> wrote:
Hi,

There is another possibility using a Scala compiler plugin for delimited continuations created by Tiark Rompf. Currently, it lives in the Scala SVN under

http://lampsvn.epfl.ch/trac/scala/browser/compiler-plugins/continuations/trunk

Using this plugin your actor code can be written as follows (sleeping code simplified):

object Sleep {
 import ActorUtils._

 def sleep(delta: Long): Unit @suspendable = {
   self ! 'Awake
   proceed (react) { case 'Awake => println("Awoken") }
 }

 def main(args: Array[String]) {
   actor {
     reset {
       println("A")
       sleep(1000)
       println("B")
     }
   }
 }
}

Note that I have put a `reset` around the block that contains the invocation of `sleep`. This defines the boundaries of the continuation context that you are saving inside `sleep` (or any other method that captures the current continuation).

The actual continuation is captured by `proceed` which is called inside `sleep. It is used to extend the closure saved by `react` with the current continuation up to the next enclosing `reset`. Note that all code that uses continuation-capturing methods must be `@suspendable`, i.e. transformed by the compiler plugin.

The `proceed` utility function is defined in the `ActorUtils` object:

object ActorUtils {
 def proceed[A, B](fun: PartialFunction[A, Unit] => Nothing):
   PartialFunction[A, B] => B @cps[Unit, Unit] =
     (caseBlock: PartialFunction[A, B]) =>
       shift[B, Unit, Unit]((k: B => Unit) => fun(caseBlock andThen k))
}

Basically, what this function does is it takes a closure-saving function, such as `react`, and turns it into a function that takes a block of cases (`caseBlock`), just like `react`, except that `caseBlock` has a result type `B`, since we can continue processing a value of that type. `shift` captures the current continuation, and invokes its argument function with it. In this case we call the original closure-saving function (`react`), but with a closure that is extended with the continuation (we pass the continuation into `react`).

The performance of this approach should be comparable to Kilim. However, keep in mind that Scala's actors have many more features than Kilim (such as message pattern matching, `Actor.self`, implicit sender ID, threads interop, and actor links) which currently lead to a certain overhead. It is not easy to implement these features without paying for it.
I am not sure whether Kilim uses Lea's FJTask framework like Scala's actors. It is faster than using a standard Java 5 executor, since it avoids a central queue for incoming tasks.

Cheers,
Philipp


Sciss wrote:
ok, thanks for the example. but isn't react particularly synchronous,  "detaching" the actor instead of "suspending" it, and not asynchronous?

i am in fact looking for a synchronous thing, to create cooperative  multitasking (coroutines).

i'm looking into kilim in this moment, see if i can get it to weave  on top of my scala bytecode. the performance seems interesting, and  the author mentions somewhere that it would be easy to write a custom  scheduler to allow logical time advancing, which is exactly what i'm  looking after....

cheers, -sciss-


Am 13.02.2009 um 12:07 schrieb Rich Dougherty:

On Fri, Feb 13, 2009 at 2:54 PM, Sciss <contact@sciss.de> wrote:
isn't there a way to implement the sleep method that it can  determine the
current execution context / continuation, and then throught the
SuspendActorException, so that execution is resumed with println ( "B" )....
? is there any way to hide the andThen chains and the necessity to  nest
functions inside functions?
There's no automatic way you can do it, but you can avoid andThen and
nesting by using a for loop's syntactic sugar. See for example
Responder.

 http://scala.sygneca.com/libs/responder
 http://www.scala-lang.org/docu/files/api/scala/Responder.html

I have done a similar thing for linking together asynchronous
operations (like react). Below is an example that uses react to get
two numbers, then sends the result to another actor. The functions
"areact" and "async0" create AsyncFunctions - functions that return
their result asynchronously. These are joined together by the for loop
into a big AsyncFunction. The whole thing is then executed with the
"->" operator and the result sent to the continuation created by the
"fc0" method.

     (for (
       x <- areact { case i: Int => i };
       _ <- async0 { println("Received " + x) };
       y <- areact { case i: Int => i };
       _ <- async0 { println("Received " + y) };
       _ <- async0 { caller ! (x + y) })
       yield ()) -> fc0(())(thrower)

Here's your sleep example, written another way:

   (for (
     _ <- async0 { println("A") };
     _ <- asleep(666);
     _ <- async0 { println("B") })
             yield ()).toFunction.apply

In this case, instead of sending the result to a continuation with the
"->" operator, I convert the AsyncFunction into a synchronous
Function0, and apply it directly.

The for loop syntax is not pretty - I don't know if it's much better
than using andThen! But if you're interested, you can see the
implementation of AsyncFunctions in the "controlflow" module of Scala
OTP.

   http://github.com/richdougherty/scala-otp

Cheers
Rich

--
http://www.richdougherty.com/



imaier
Joined: 2008-07-01,
User offline. Last seen 23 weeks 2 days ago.
Re: Actors: Creating a continuation context

As I understand, the continuations plugin will be part of the
distribution, once it proves to be sufficiently stable. I use it in the
reactive part of ScalaFX, and it works pretty well already. For the IDE,
I only know about eclipse. You just need to specify the plugin directory
in the project properties and there you go.

Ingo

Stephane Le Dorze wrote:
> Speaking of Compiler plugins..
> Will some of them will be part of the standard distribution?
> How will that play with IDE using the compiler?
> Thanks for any pointers..
> Stephane
>
> On Mon, Feb 16, 2009 at 3:36 PM, Philipp Haller
> wrote:
>
> Hi,
>
> There is another possibility using a Scala compiler plugin for
> delimited continuations created by Tiark Rompf. Currently, it lives
> in the Scala SVN under
>
> http://lampsvn.epfl.ch/trac/scala/browser/compiler-plugins/continuations...
>
> Using this plugin your actor code can be written as follows
> (sleeping code simplified):
>
> object Sleep {
> import ActorUtils._
>
> def sleep(delta: Long): Unit @suspendable = {
> self ! 'Awake
> proceed (react) { case 'Awake => println("Awoken") }
> }
>
> def main(args: Array[String]) {
> actor {
> reset {
> println("A")
> sleep(1000)
> println("B")
> }
> }
> }
> }
>
> Note that I have put a `reset` around the block that contains the
> invocation of `sleep`. This defines the boundaries of the
> continuation context that you are saving inside `sleep` (or any
> other method that captures the current continuation).
>
> The actual continuation is captured by `proceed` which is called
> inside `sleep. It is used to extend the closure saved by `react`
> with the current continuation up to the next enclosing `reset`. Note
> that all code that uses continuation-capturing methods must be
> `@suspendable`, i.e. transformed by the compiler plugin.
>
> The `proceed` utility function is defined in the `ActorUtils` object:
>
> object ActorUtils {
> def proceed[A, B](fun: PartialFunction[A, Unit] => Nothing):
> PartialFunction[A, B] => B @cps[Unit, Unit] =
> (caseBlock: PartialFunction[A, B]) =>
> shift[B, Unit, Unit]((k: B => Unit) => fun(caseBlock andThen k))
> }
>
> Basically, what this function does is it takes a closure-saving
> function, such as `react`, and turns it into a function that takes a
> block of cases (`caseBlock`), just like `react`, except that
> `caseBlock` has a result type `B`, since we can continue processing
> a value of that type. `shift` captures the current continuation, and
> invokes its argument function with it. In this case we call the
> original closure-saving function (`react`), but with a closure that
> is extended with the continuation (we pass the continuation into
> `react`).
>
> The performance of this approach should be comparable to Kilim.
> However, keep in mind that Scala's actors have many more features
> than Kilim (such as message pattern matching, `Actor.self`, implicit
> sender ID, threads interop, and actor links) which currently lead to
> a certain overhead. It is not easy to implement these features
> without paying for it.
> I am not sure whether Kilim uses Lea's FJTask framework like Scala's
> actors. It is faster than using a standard Java 5 executor, since it
> avoids a central queue for incoming tasks.
>
> Cheers,
> Philipp
>
>
>
> Sciss wrote:
>
> ok, thanks for the example. but isn't react particularly
> synchronous, "detaching" the actor instead of "suspending" it,
> and not asynchronous?
>
> i am in fact looking for a synchronous thing, to create
> cooperative multitasking (coroutines).
>
> i'm looking into kilim in this moment, see if i can get it to
> weave on top of my scala bytecode. the performance seems
> interesting, and the author mentions somewhere that it would be
> easy to write a custom scheduler to allow logical time
> advancing, which is exactly what i'm looking after....
>
> cheers, -sciss-
>
>
> Am 13.02.2009 um 12:07 schrieb Rich Dougherty:
>
> On Fri, Feb 13, 2009 at 2:54 PM, Sciss > wrote:
>
> isn't there a way to implement the sleep method that it
> can determine the
> current execution context / continuation, and then
> throught the
> SuspendActorException, so that execution is resumed with
> println ( "B" )....
> ? is there any way to hide the andThen chains and the
> necessity to nest
> functions inside functions?
>
> There's no automatic way you can do it, but you can avoid
> andThen and
> nesting by using a for loop's syntactic sugar. See for example
> Responder.
>
> http://scala.sygneca.com/libs/responder
> http://www.scala-lang.org/docu/files/api/scala/Responder.html
>
> I have done a similar thing for linking together asynchronous
> operations (like react). Below is an example that uses react
> to get
> two numbers, then sends the result to another actor. The
> functions
> "areact" and "async0" create AsyncFunctions - functions that
> return
> their result asynchronously. These are joined together by
> the for loop
> into a big AsyncFunction. The whole thing is then executed
> with the
> "->" operator and the result sent to the continuation
> created by the
> "fc0" method.
>
> (for (
> x <- areact { case i: Int => i };
> _ <- async0 { println("Received " + x) };
> y <- areact { case i: Int => i };
> _ <- async0 { println("Received " + y) };
> _ <- async0 { caller ! (x + y) })
> yield ()) -> fc0(())(thrower)
>
> Here's your sleep example, written another way:
>
> (for (
> _ <- async0 { println("A") };
> _ <- asleep(666);
> _ <- async0 { println("B") })
> yield ()).toFunction.apply
>
> In this case, instead of sending the result to a
> continuation with the
> "->" operator, I convert the AsyncFunction into a synchronous
> Function0, and apply it directly.
>
> The for loop syntax is not pretty - I don't know if it's
> much better
> than using andThen! But if you're interested, you can see the
> implementation of AsyncFunctions in the "controlflow" module
> of Scala
> OTP.
>
> http://github.com/richdougherty/scala-otp
>
> Cheers
> Rich
>
> --
> http://www.richdougherty.com/
>
>
>
>

StephaneLD
Joined: 2008-08-28,
User offline. Last seen 4 years 9 weeks ago.
Re: Actors: Creating a continuation context
What I liked within Nemerle was the ability to create Macro in the code (or Library). It would be nice if the compiler could handle plugins in a similar way.
It will give us more flexibility; like using Maven to retrieve a compiler plugin a Library needs to compile.. (not mentionning the version)
I don't know if this is possible; but we have to consider distribution very seriously if we want all this power to be really used - IMHO.
Stephane

On Mon, Feb 16, 2009 at 5:12 PM, Ingo Maier <ingo.maier@epfl.ch> wrote:
As I understand, the continuations plugin will be part of the distribution, once it proves to be sufficiently stable. I use it in the reactive part of ScalaFX, and it works pretty well already. For the IDE, I only know about eclipse. You just need to specify the plugin directory in the project properties and there you go.

Ingo

Stephane Le Dorze wrote:
Speaking of Compiler plugins..
Will some of them will be part of the standard distribution?
How will that play with IDE using the compiler?
Thanks for any pointers..
Stephane

On Mon, Feb 16, 2009 at 3:36 PM, Philipp Haller <philipp.haller@epfl.ch> wrote:

   Hi,

   There is another possibility using a Scala compiler plugin for
   delimited continuations created by Tiark Rompf. Currently, it lives
   in the Scala SVN under

   http://lampsvn.epfl.ch/trac/scala/browser/compiler-plugins/continuations/trunk

   Using this plugin your actor code can be written as follows
   (sleeping code simplified):

   object Sleep {
    import ActorUtils._

    def sleep(delta: Long): Unit @suspendable = {
      self ! 'Awake
      proceed (react) { case 'Awake => println("Awoken") }
    }

    def main(args: Array[String]) {
      actor {
        reset {
          println("A")
          sleep(1000)
          println("B")
        }
      }
    }
   }

   Note that I have put a `reset` around the block that contains the
   invocation of `sleep`. This defines the boundaries of the
   continuation context that you are saving inside `sleep` (or any
   other method that captures the current continuation).

   The actual continuation is captured by `proceed` which is called
   inside `sleep. It is used to extend the closure saved by `react`
   with the current continuation up to the next enclosing `reset`. Note
   that all code that uses continuation-capturing methods must be
   `@suspendable`, i.e. transformed by the compiler plugin.

   The `proceed` utility function is defined in the `ActorUtils` object:

   object ActorUtils {
    def proceed[A, B](fun: PartialFunction[A, Unit] => Nothing):
      PartialFunction[A, B] => B @cps[Unit, Unit] =
        (caseBlock: PartialFunction[A, B]) =>
          shift[B, Unit, Unit]((k: B => Unit) => fun(caseBlock andThen k))
   }

   Basically, what this function does is it takes a closure-saving
   function, such as `react`, and turns it into a function that takes a
   block of cases (`caseBlock`), just like `react`, except that
   `caseBlock` has a result type `B`, since we can continue processing
   a value of that type. `shift` captures the current continuation, and
   invokes its argument function with it. In this case we call the
   original closure-saving function (`react`), but with a closure that
   is extended with the continuation (we pass the continuation into
   `react`).

   The performance of this approach should be comparable to Kilim.
   However, keep in mind that Scala's actors have many more features
   than Kilim (such as message pattern matching, `Actor.self`, implicit
   sender ID, threads interop, and actor links) which currently lead to
   a certain overhead. It is not easy to implement these features
   without paying for it.
   I am not sure whether Kilim uses Lea's FJTask framework like Scala's
   actors. It is faster than using a standard Java 5 executor, since it
   avoids a central queue for incoming tasks.

   Cheers,
   Philipp



   Sciss wrote:

       ok, thanks for the example. but isn't react particularly
       synchronous,  "detaching" the actor instead of "suspending" it,
       and not asynchronous?

       i am in fact looking for a synchronous thing, to create
       cooperative  multitasking (coroutines).

       i'm looking into kilim in this moment, see if i can get it to
       weave  on top of my scala bytecode. the performance seems
       interesting, and  the author mentions somewhere that it would be
       easy to write a custom  scheduler to allow logical time
       advancing, which is exactly what i'm  looking after....

       cheers, -sciss-


       Am 13.02.2009 um 12:07 schrieb Rich Dougherty:

           On Fri, Feb 13, 2009 at 2:54 PM, Sciss <contact@sciss.de
           <mailto:contact@sciss.de>> wrote:

               isn't there a way to implement the sleep method that it
               can  determine the
               current execution context / continuation, and then
               throught the
               SuspendActorException, so that execution is resumed with
               println ( "B" )....
               ? is there any way to hide the andThen chains and the
               necessity to  nest
               functions inside functions?

           There's no automatic way you can do it, but you can avoid
           andThen and
           nesting by using a for loop's syntactic sugar. See for example
           Responder.

            http://scala.sygneca.com/libs/responder
            http://www.scala-lang.org/docu/files/api/scala/Responder.html

           I have done a similar thing for linking together asynchronous
           operations (like react). Below is an example that uses react
           to get
           two numbers, then sends the result to another actor. The
           functions
           "areact" and "async0" create AsyncFunctions - functions that
           return
           their result asynchronously. These are joined together by
           the for loop
           into a big AsyncFunction. The whole thing is then executed
           with the
           "->" operator and the result sent to the continuation
           created by the
           "fc0" method.

                (for (
                  x <- areact { case i: Int => i };
                  _ <- async0 { println("Received " + x) };
                  y <- areact { case i: Int => i };
                  _ <- async0 { println("Received " + y) };
                  _ <- async0 { caller ! (x + y) })
                  yield ()) -> fc0(())(thrower)

           Here's your sleep example, written another way:

              (for (
                _ <- async0 { println("A") };
                _ <- asleep(666);
                _ <- async0 { println("B") })
                        yield ()).toFunction.apply

           In this case, instead of sending the result to a
           continuation with the
           "->" operator, I convert the AsyncFunction into a synchronous
           Function0, and apply it directly.

           The for loop syntax is not pretty - I don't know if it's
           much better
           than using andThen! But if you're interested, you can see the
           implementation of AsyncFunctions in the "controlflow" module
           of Scala
           OTP.

              http://github.com/richdougherty/scala-otp

           Cheers
           Rich

           --
           http://www.richdougherty.com/






Sciss
Joined: 2008-12-17,
User offline. Last seen 28 weeks 5 days ago.
Re: Actors: Creating a continuation context

hi,

thank you for the link to this project. regarding your example, i
cannot find any information about your ActorUtils import. i imported
scala.actors.Actor._ and scala.continuations.ControlContext._
instead. However, scalac cannot deal with the "proceed" statement, so
i'm unable to compile this. also can you give me a link to the
documentation of scala.continuations, google didn't give me anything
useful and the examples are not commented.

thanks! ciao, -sciss-

object Sleep {
// import ActorUtils._
import scala.actors.Actor._
import scala.continuations.ControlContext._

def sleep(delta: Long): Unit @suspendable = {
self ! 'Awake
proceed (react) { case 'Awake => println("Awoken") } // proceed
is unknown .... where is it defined??
}

def main(args: Array[String]) {
actor {
reset {
println("A")
sleep(1000)
println("B")
}
}
}
}

Am 16.02.2009 um 15:36 schrieb Philipp Haller:

> Hi,
>
> There is another possibility using a Scala compiler plugin for
> delimited continuations created by Tiark Rompf. Currently, it lives
> in the Scala SVN under
>
> http://lampsvn.epfl.ch/trac/scala/browser/compiler-plugins/
> continuations/trunk
>
> Using this plugin your actor code can be written as follows
> (sleeping code simplified):
>
> object Sleep {
> import ActorUtils._
>
> def sleep(delta: Long): Unit @suspendable = {
> self ! 'Awake
> proceed (react) { case 'Awake => println("Awoken") }
> }
>
> def main(args: Array[String]) {
> actor {
> reset {
> println("A")
> sleep(1000)
> println("B")
> }
> }
> }
> }
>
> Note that I have put a `reset` around the block that contains the
> invocation of `sleep`. This defines the boundaries of the
> continuation context that you are saving inside `sleep` (or any
> other method that captures the current continuation).
>
> The actual continuation is captured by `proceed` which is called
> inside `sleep. It is used to extend the closure saved by `react`
> with the current continuation up to the next enclosing `reset`.
> Note that all code that uses continuation-capturing methods must be
> `@suspendable`, i.e. transformed by the compiler plugin.
>
> The `proceed` utility function is defined in the `ActorUtils` object:
>
> object ActorUtils {
> def proceed[A, B](fun: PartialFunction[A, Unit] => Nothing):
> PartialFunction[A, B] => B @cps[Unit, Unit] =
> (caseBlock: PartialFunction[A, B]) =>
> shift[B, Unit, Unit]((k: B => Unit) => fun(caseBlock
> andThen k))
> }
>
> Basically, what this function does is it takes a closure-saving
> function, such as `react`, and turns it into a function that takes
> a block of cases (`caseBlock`), just like `react`, except that
> `caseBlock` has a result type `B`, since we can continue processing
> a value of that type. `shift` captures the current continuation,
> and invokes its argument function with it. In this case we call the
> original closure-saving function (`react`), but with a closure that
> is extended with the continuation (we pass the continuation into
> `react`).
>
> The performance of this approach should be comparable to Kilim.
> However, keep in mind that Scala's actors have many more features
> than Kilim (such as message pattern matching, `Actor.self`,
> implicit sender ID, threads interop, and actor links) which
> currently lead to a certain overhead. It is not easy to implement
> these features without paying for it.
> I am not sure whether Kilim uses Lea's FJTask framework like
> Scala's actors. It is faster than using a standard Java 5 executor,
> since it avoids a central queue for incoming tasks.
>
> Cheers,
> Philipp
>
>
> Sciss wrote:
>> ok, thanks for the example. but isn't react particularly
>> synchronous, "detaching" the actor instead of "suspending" it,
>> and not asynchronous?
>> i am in fact looking for a synchronous thing, to create
>> cooperative multitasking (coroutines).
>> i'm looking into kilim in this moment, see if i can get it to
>> weave on top of my scala bytecode. the performance seems
>> interesting, and the author mentions somewhere that it would be
>> easy to write a custom scheduler to allow logical time advancing,
>> which is exactly what i'm looking after....
>> cheers, -sciss-
>> Am 13.02.2009 um 12:07 schrieb Rich Dougherty:
>>> On Fri, Feb 13, 2009 at 2:54 PM, Sciss wrote:
>>>> isn't there a way to implement the sleep method that it can
>>>> determine the
>>>> current execution context / continuation, and then throught the
>>>> SuspendActorException, so that execution is resumed with println
>>>> ( "B" )....
>>>> ? is there any way to hide the andThen chains and the necessity
>>>> to nest
>>>> functions inside functions?
>>> There's no automatic way you can do it, but you can avoid andThen
>>> and
>>> nesting by using a for loop's syntactic sugar. See for example
>>> Responder.
>>>
>>> http://scala.sygneca.com/libs/responder
>>> http://www.scala-lang.org/docu/files/api/scala/Responder.html
>>>
>>> I have done a similar thing for linking together asynchronous
>>> operations (like react). Below is an example that uses react to get
>>> two numbers, then sends the result to another actor. The functions
>>> "areact" and "async0" create AsyncFunctions - functions that return
>>> their result asynchronously. These are joined together by the for
>>> loop
>>> into a big AsyncFunction. The whole thing is then executed with the
>>> "->" operator and the result sent to the continuation created by the
>>> "fc0" method.
>>>
>>> (for (
>>> x <- areact { case i: Int => i };
>>> _ <- async0 { println("Received " + x) };
>>> y <- areact { case i: Int => i };
>>> _ <- async0 { println("Received " + y) };
>>> _ <- async0 { caller ! (x + y) })
>>> yield ()) -> fc0(())(thrower)
>>>
>>> Here's your sleep example, written another way:
>>>
>>> (for (
>>> _ <- async0 { println("A") };
>>> _ <- asleep(666);
>>> _ <- async0 { println("B") })
>>> yield ()).toFunction.apply
>>>
>>> In this case, instead of sending the result to a continuation
>>> with the
>>> "->" operator, I convert the AsyncFunction into a synchronous
>>> Function0, and apply it directly.
>>>
>>> The for loop syntax is not pretty - I don't know if it's much better
>>> than using andThen! But if you're interested, you can see the
>>> implementation of AsyncFunctions in the "controlflow" module of
>>> Scala
>>> OTP.
>>>
>>> http://github.com/richdougherty/scala-otp
>>>
>>> Cheers
>>> Rich
>>>
>>> --
>>> http://www.richdougherty.com/
>

Sciss
Joined: 2008-12-17,
User offline. Last seen 28 weeks 5 days ago.
Re: Actors: Creating a continuation context

ok.... sorry i should have read more carefully. so i copied and
pasted your 'proceed' method into my code. i managed to compile and
run from the command line (still don't know how to add the compiler-
plugin to needbeans). so... i guess to make your example release
sleep for awhile i would take out "self ! 'Awake" and instead send a
message to the scheduler. will try that out.

anyway, question remains if there is any documentation about
scala.continuations, since this is pretty difficult for me to
understand.

thanks, -sciss-

Am 17.02.2009 um 17:26 schrieb Sciss:

> hi,
>
> thank you for the link to this project. regarding your example, i
> cannot find any information about your ActorUtils import. i
> imported scala.actors.Actor._ and
> scala.continuations.ControlContext._ instead. However, scalac
> cannot deal with the "proceed" statement, so i'm unable to compile
> this. also can you give me a link to the documentation of
> scala.continuations, google didn't give me anything useful and the
> examples are not commented.
>
> thanks! ciao, -sciss-
>
>
> object Sleep {
> // import ActorUtils._
> import scala.actors.Actor._
> import scala.continuations.ControlContext._
>
> def sleep(delta: Long): Unit @suspendable = {
> self ! 'Awake
> proceed (react) { case 'Awake => println("Awoken") } //
> proceed is unknown .... where is it defined??
> }
>
> def main(args: Array[String]) {
> actor {
> reset {
> println("A")
> sleep(1000)
> println("B")
> }
> }
> }
> }
>
>
> Am 16.02.2009 um 15:36 schrieb Philipp Haller:
>
>> Hi,
>>
>> There is another possibility using a Scala compiler plugin for
>> delimited continuations created by Tiark Rompf. Currently, it
>> lives in the Scala SVN under
>>
>> http://lampsvn.epfl.ch/trac/scala/browser/compiler-plugins/
>> continuations/trunk
>>
>> Using this plugin your actor code can be written as follows
>> (sleeping code simplified):
>>
>> object Sleep {
>> import ActorUtils._
>>
>> def sleep(delta: Long): Unit @suspendable = {
>> self ! 'Awake
>> proceed (react) { case 'Awake => println("Awoken") }
>> }
>>
>> def main(args: Array[String]) {
>> actor {
>> reset {
>> println("A")
>> sleep(1000)
>> println("B")
>> }
>> }
>> }
>> }
>>
>> Note that I have put a `reset` around the block that contains the
>> invocation of `sleep`. This defines the boundaries of the
>> continuation context that you are saving inside `sleep` (or any
>> other method that captures the current continuation).
>>
>> The actual continuation is captured by `proceed` which is called
>> inside `sleep. It is used to extend the closure saved by `react`
>> with the current continuation up to the next enclosing `reset`.
>> Note that all code that uses continuation-capturing methods must
>> be `@suspendable`, i.e. transformed by the compiler plugin.
>>
>> The `proceed` utility function is defined in the `ActorUtils` object:
>>
>> object ActorUtils {
>> def proceed[A, B](fun: PartialFunction[A, Unit] => Nothing):
>> PartialFunction[A, B] => B @cps[Unit, Unit] =
>> (caseBlock: PartialFunction[A, B]) =>
>> shift[B, Unit, Unit]((k: B => Unit) => fun(caseBlock
>> andThen k))
>> }
>>
>> Basically, what this function does is it takes a closure-saving
>> function, such as `react`, and turns it into a function that takes
>> a block of cases (`caseBlock`), just like `react`, except that
>> `caseBlock` has a result type `B`, since we can continue
>> processing a value of that type. `shift` captures the current
>> continuation, and invokes its argument function with it. In this
>> case we call the original closure-saving function (`react`), but
>> with a closure that is extended with the continuation (we pass the
>> continuation into `react`).
>>
>> The performance of this approach should be comparable to Kilim.
>> However, keep in mind that Scala's actors have many more features
>> than Kilim (such as message pattern matching, `Actor.self`,
>> implicit sender ID, threads interop, and actor links) which
>> currently lead to a certain overhead. It is not easy to implement
>> these features without paying for it.
>> I am not sure whether Kilim uses Lea's FJTask framework like
>> Scala's actors. It is faster than using a standard Java 5
>> executor, since it avoids a central queue for incoming tasks.
>>
>> Cheers,
>> Philipp
>>
>>
>> Sciss wrote:
>>> ok, thanks for the example. but isn't react particularly
>>> synchronous, "detaching" the actor instead of "suspending" it,
>>> and not asynchronous?
>>> i am in fact looking for a synchronous thing, to create
>>> cooperative multitasking (coroutines).
>>> i'm looking into kilim in this moment, see if i can get it to
>>> weave on top of my scala bytecode. the performance seems
>>> interesting, and the author mentions somewhere that it would be
>>> easy to write a custom scheduler to allow logical time
>>> advancing, which is exactly what i'm looking after....
>>> cheers, -sciss-
>>> Am 13.02.2009 um 12:07 schrieb Rich Dougherty:
>>>> On Fri, Feb 13, 2009 at 2:54 PM, Sciss wrote:
>>>>> isn't there a way to implement the sleep method that it can
>>>>> determine the
>>>>> current execution context / continuation, and then throught the
>>>>> SuspendActorException, so that execution is resumed with
>>>>> println ( "B" )....
>>>>> ? is there any way to hide the andThen chains and the necessity
>>>>> to nest
>>>>> functions inside functions?
>>>> There's no automatic way you can do it, but you can avoid
>>>> andThen and
>>>> nesting by using a for loop's syntactic sugar. See for example
>>>> Responder.
>>>>
>>>> http://scala.sygneca.com/libs/responder
>>>> http://www.scala-lang.org/docu/files/api/scala/Responder.html
>>>>
>>>> I have done a similar thing for linking together asynchronous
>>>> operations (like react). Below is an example that uses react to get
>>>> two numbers, then sends the result to another actor. The functions
>>>> "areact" and "async0" create AsyncFunctions - functions that return
>>>> their result asynchronously. These are joined together by the
>>>> for loop
>>>> into a big AsyncFunction. The whole thing is then executed with the
>>>> "->" operator and the result sent to the continuation created by
>>>> the
>>>> "fc0" method.
>>>>
>>>> (for (
>>>> x <- areact { case i: Int => i };
>>>> _ <- async0 { println("Received " + x) };
>>>> y <- areact { case i: Int => i };
>>>> _ <- async0 { println("Received " + y) };
>>>> _ <- async0 { caller ! (x + y) })
>>>> yield ()) -> fc0(())(thrower)
>>>>
>>>> Here's your sleep example, written another way:
>>>>
>>>> (for (
>>>> _ <- async0 { println("A") };
>>>> _ <- asleep(666);
>>>> _ <- async0 { println("B") })
>>>> yield ()).toFunction.apply
>>>>
>>>> In this case, instead of sending the result to a continuation
>>>> with the
>>>> "->" operator, I convert the AsyncFunction into a synchronous
>>>> Function0, and apply it directly.
>>>>
>>>> The for loop syntax is not pretty - I don't know if it's much
>>>> better
>>>> than using andThen! But if you're interested, you can see the
>>>> implementation of AsyncFunctions in the "controlflow" module of
>>>> Scala
>>>> OTP.
>>>>
>>>> http://github.com/richdougherty/scala-otp
>>>>
>>>> Cheers
>>>> Rich
>>>>
>>>> --
>>>> http://www.richdougherty.com/
>>
>

Sciss
Joined: 2008-12-17,
User offline. Last seen 28 weeks 5 days ago.
Re: Actors: Creating a continuation context

yippieee, seems to work...

def sleep(delta: Long): Unit @suspendable = {
sched ! Reschedule( 1000, self )
proceed (react) { case Awake => println("Awoken") }
}

thanks a bunch philipp, will try to continue this trail.

Am 17.02.2009 um 18:50 schrieb Sciss:

> ok.... sorry i should have read more carefully. so i copied and
> pasted your 'proceed' method into my code. i managed to compile and
> run from the command line (still don't know how to add the compiler-
> plugin to needbeans). so... i guess to make your example release
> sleep for awhile i would take out "self ! 'Awake" and instead send
> a message to the scheduler. will try that out.
>
> anyway, question remains if there is any documentation about
> scala.continuations, since this is pretty difficult for me to
> understand.
>
> thanks, -sciss-
>
>
> Am 17.02.2009 um 17:26 schrieb Sciss:
>
>> hi,
>>
>> thank you for the link to this project. regarding your example, i
>> cannot find any information about your ActorUtils import. i
>> imported scala.actors.Actor._ and
>> scala.continuations.ControlContext._ instead. However, scalac
>> cannot deal with the "proceed" statement, so i'm unable to compile
>> this. also can you give me a link to the documentation of
>> scala.continuations, google didn't give me anything useful and the
>> examples are not commented.
>>
>> thanks! ciao, -sciss-
>>
>>
>> object Sleep {
>> // import ActorUtils._
>> import scala.actors.Actor._
>> import scala.continuations.ControlContext._
>>
>> def sleep(delta: Long): Unit @suspendable = {
>> self ! 'Awake
>> proceed (react) { case 'Awake => println("Awoken") } //
>> proceed is unknown .... where is it defined??
>> }
>>
>> def main(args: Array[String]) {
>> actor {
>> reset {
>> println("A")
>> sleep(1000)
>> println("B")
>> }
>> }
>> }
>> }
>>
>>
>> Am 16.02.2009 um 15:36 schrieb Philipp Haller:
>>
>>> Hi,
>>>
>>> There is another possibility using a Scala compiler plugin for
>>> delimited continuations created by Tiark Rompf. Currently, it
>>> lives in the Scala SVN under
>>>
>>> http://lampsvn.epfl.ch/trac/scala/browser/compiler-plugins/
>>> continuations/trunk
>>>
>>> Using this plugin your actor code can be written as follows
>>> (sleeping code simplified):
>>>
>>> object Sleep {
>>> import ActorUtils._
>>>
>>> def sleep(delta: Long): Unit @suspendable = {
>>> self ! 'Awake
>>> proceed (react) { case 'Awake => println("Awoken") }
>>> }
>>>
>>> def main(args: Array[String]) {
>>> actor {
>>> reset {
>>> println("A")
>>> sleep(1000)
>>> println("B")
>>> }
>>> }
>>> }
>>> }
>>>
>>> Note that I have put a `reset` around the block that contains the
>>> invocation of `sleep`. This defines the boundaries of the
>>> continuation context that you are saving inside `sleep` (or any
>>> other method that captures the current continuation).
>>>
>>> The actual continuation is captured by `proceed` which is called
>>> inside `sleep. It is used to extend the closure saved by `react`
>>> with the current continuation up to the next enclosing `reset`.
>>> Note that all code that uses continuation-capturing methods must
>>> be `@suspendable`, i.e. transformed by the compiler plugin.
>>>
>>> The `proceed` utility function is defined in the `ActorUtils`
>>> object:
>>>
>>> object ActorUtils {
>>> def proceed[A, B](fun: PartialFunction[A, Unit] => Nothing):
>>> PartialFunction[A, B] => B @cps[Unit, Unit] =
>>> (caseBlock: PartialFunction[A, B]) =>
>>> shift[B, Unit, Unit]((k: B => Unit) => fun(caseBlock
>>> andThen k))
>>> }
>>>
>>> Basically, what this function does is it takes a closure-saving
>>> function, such as `react`, and turns it into a function that
>>> takes a block of cases (`caseBlock`), just like `react`, except
>>> that `caseBlock` has a result type `B`, since we can continue
>>> processing a value of that type. `shift` captures the current
>>> continuation, and invokes its argument function with it. In this
>>> case we call the original closure-saving function (`react`), but
>>> with a closure that is extended with the continuation (we pass
>>> the continuation into `react`).
>>>
>>> The performance of this approach should be comparable to Kilim.
>>> However, keep in mind that Scala's actors have many more features
>>> than Kilim (such as message pattern matching, `Actor.self`,
>>> implicit sender ID, threads interop, and actor links) which
>>> currently lead to a certain overhead. It is not easy to implement
>>> these features without paying for it.
>>> I am not sure whether Kilim uses Lea's FJTask framework like
>>> Scala's actors. It is faster than using a standard Java 5
>>> executor, since it avoids a central queue for incoming tasks.
>>>
>>> Cheers,
>>> Philipp
>>>
>>>
>>> Sciss wrote:
>>>> ok, thanks for the example. but isn't react particularly
>>>> synchronous, "detaching" the actor instead of "suspending" it,
>>>> and not asynchronous?
>>>> i am in fact looking for a synchronous thing, to create
>>>> cooperative multitasking (coroutines).
>>>> i'm looking into kilim in this moment, see if i can get it to
>>>> weave on top of my scala bytecode. the performance seems
>>>> interesting, and the author mentions somewhere that it would be
>>>> easy to write a custom scheduler to allow logical time
>>>> advancing, which is exactly what i'm looking after....
>>>> cheers, -sciss-
>>>> Am 13.02.2009 um 12:07 schrieb Rich Dougherty:
>>>>> On Fri, Feb 13, 2009 at 2:54 PM, Sciss wrote:
>>>>>> isn't there a way to implement the sleep method that it can
>>>>>> determine the
>>>>>> current execution context / continuation, and then throught the
>>>>>> SuspendActorException, so that execution is resumed with
>>>>>> println ( "B" )....
>>>>>> ? is there any way to hide the andThen chains and the
>>>>>> necessity to nest
>>>>>> functions inside functions?
>>>>> There's no automatic way you can do it, but you can avoid
>>>>> andThen and
>>>>> nesting by using a for loop's syntactic sugar. See for example
>>>>> Responder.
>>>>>
>>>>> http://scala.sygneca.com/libs/responder
>>>>> http://www.scala-lang.org/docu/files/api/scala/Responder.html
>>>>>
>>>>> I have done a similar thing for linking together asynchronous
>>>>> operations (like react). Below is an example that uses react to
>>>>> get
>>>>> two numbers, then sends the result to another actor. The functions
>>>>> "areact" and "async0" create AsyncFunctions - functions that
>>>>> return
>>>>> their result asynchronously. These are joined together by the
>>>>> for loop
>>>>> into a big AsyncFunction. The whole thing is then executed with
>>>>> the
>>>>> "->" operator and the result sent to the continuation created
>>>>> by the
>>>>> "fc0" method.
>>>>>
>>>>> (for (
>>>>> x <- areact { case i: Int => i };
>>>>> _ <- async0 { println("Received " + x) };
>>>>> y <- areact { case i: Int => i };
>>>>> _ <- async0 { println("Received " + y) };
>>>>> _ <- async0 { caller ! (x + y) })
>>>>> yield ()) -> fc0(())(thrower)
>>>>>
>>>>> Here's your sleep example, written another way:
>>>>>
>>>>> (for (
>>>>> _ <- async0 { println("A") };
>>>>> _ <- asleep(666);
>>>>> _ <- async0 { println("B") })
>>>>> yield ()).toFunction.apply
>>>>>
>>>>> In this case, instead of sending the result to a continuation
>>>>> with the
>>>>> "->" operator, I convert the AsyncFunction into a synchronous
>>>>> Function0, and apply it directly.
>>>>>
>>>>> The for loop syntax is not pretty - I don't know if it's much
>>>>> better
>>>>> than using andThen! But if you're interested, you can see the
>>>>> implementation of AsyncFunctions in the "controlflow" module of
>>>>> Scala
>>>>> OTP.
>>>>>
>>>>> http://github.com/richdougherty/scala-otp
>>>>>
>>>>> Cheers
>>>>> Rich
>>>>>
>>>>> --
>>>>> http://www.richdougherty.com/
>>>
>>
>

Sciss
Joined: 2008-12-17,
User offline. Last seen 28 weeks 5 days ago.
Re: Actors: Creating a continuation context

....unfortunately there is more problems. this works:

fork {
sleep( 666 )
println( "step" )
sleep( 1000 )
println( "done" )
}

this doesn't:

fork {
for( i <- (0 until 10) ) { ... }
println( "i = " + i )
sleep( 500 )
}
println( "done" )
}

// ---> polymorphic expression cannot be instantiated to expected
type; found : [C]de.sciss.tint.sc.Routine[Unit,C] required: Unit
?

but it compiles if i do

fork {
for( i <- (0 until 10) ) { ... }
println( "i = " + i )
sleep( 500 )
}
sleep( 1000 )
println( "done" )
}

// ---> but the sleep( 500 ) statements don't have any effect, code
doesn't pause ;-(

trying to exchange for a 'while' loop:

fork {
var i = 0
while( i < 10 ) {
println( "i = " + i )
sleep( 500 )
i = i + 1
}
sleep( 1000 )
println( "done" )
}

// ---> found cps expression in non-cps position
// --->then and else parts must both be cps code or neither of them
?

jesus, why is it's so complicated to get a very simple behaviour. is
the scala.continuations only a bad hack that works in a few cases but
fails in many other cases? or can the desired behaviour be achieved?

thanks once more (sorry for the posting frequency...),

-sciss-

p.s. here's the missing code

class Routine[A,C]( val clock: Clock, ctx: => (A @cps[ A, C ]))
extends Actor {
def act {
reset( ctx )
}

private def proceed[A, B](fun: PartialFunction[A, Unit] => Nothing):
PartialFunction[A, B] => B @cps[Unit, Unit] =
(caseBlock: PartialFunction[A, B]) =>
shift[B, Unit, Unit]((k: B => Unit) => fun(caseBlock
andThen k))

def sleep(delta: Long): Unit @suspendable = {
clock ! Reschedule( delta, self )
proceed( react ) { case Awake => }
}
}

def fork[A,C]( ctx: =>(A @cps[A,C]) ) = { val r = new Routine
( Clock.default, ctx ); r.start; r }
def sleep( delta: Long ): Unit @suspendable = self.asInstanceOf
[Routine[_,_]].sleep( delta )

Am 17.02.2009 um 18:59 schrieb Sciss:

> yippieee, seems to work...
>
> def sleep(delta: Long): Unit @suspendable = {
> sched ! Reschedule( 1000, self )
> proceed (react) { case Awake => println("Awoken") }
> }
>
> thanks a bunch philipp, will try to continue this trail.
>
>
> Am 17.02.2009 um 18:50 schrieb Sciss:
>
>> ok.... sorry i should have read more carefully. so i copied and
>> pasted your 'proceed' method into my code. i managed to compile
>> and run from the command line (still don't know how to add the
>> compiler-plugin to needbeans). so... i guess to make your example
>> release sleep for awhile i would take out "self ! 'Awake" and
>> instead send a message to the scheduler. will try that out.
>>
>> anyway, question remains if there is any documentation about
>> scala.continuations, since this is pretty difficult for me to
>> understand.
>>
>> thanks, -sciss-
>>
>>
>> Am 17.02.2009 um 17:26 schrieb Sciss:
>>
>>> hi,
>>>
>>> thank you for the link to this project. regarding your example, i
>>> cannot find any information about your ActorUtils import. i
>>> imported scala.actors.Actor._ and
>>> scala.continuations.ControlContext._ instead. However, scalac
>>> cannot deal with the "proceed" statement, so i'm unable to
>>> compile this. also can you give me a link to the documentation of
>>> scala.continuations, google didn't give me anything useful and
>>> the examples are not commented.
>>>
>>> thanks! ciao, -sciss-
>>>
>>>
>>> object Sleep {
>>> // import ActorUtils._
>>> import scala.actors.Actor._
>>> import scala.continuations.ControlContext._
>>>
>>> def sleep(delta: Long): Unit @suspendable = {
>>> self ! 'Awake
>>> proceed (react) { case 'Awake => println("Awoken") } //
>>> proceed is unknown .... where is it defined??
>>> }
>>>
>>> def main(args: Array[String]) {
>>> actor {
>>> reset {
>>> println("A")
>>> sleep(1000)
>>> println("B")
>>> }
>>> }
>>> }
>>> }
>>>
>>>
>>> Am 16.02.2009 um 15:36 schrieb Philipp Haller:
>>>
>>>> Hi,
>>>>
>>>> There is another possibility using a Scala compiler plugin for
>>>> delimited continuations created by Tiark Rompf. Currently, it
>>>> lives in the Scala SVN under
>>>>
>>>> http://lampsvn.epfl.ch/trac/scala/browser/compiler-plugins/
>>>> continuations/trunk
>>>>
>>>> Using this plugin your actor code can be written as follows
>>>> (sleeping code simplified):
>>>>
>>>> object Sleep {
>>>> import ActorUtils._
>>>>
>>>> def sleep(delta: Long): Unit @suspendable = {
>>>> self ! 'Awake
>>>> proceed (react) { case 'Awake => println("Awoken") }
>>>> }
>>>>
>>>> def main(args: Array[String]) {
>>>> actor {
>>>> reset {
>>>> println("A")
>>>> sleep(1000)
>>>> println("B")
>>>> }
>>>> }
>>>> }
>>>> }
>>>>
>>>> Note that I have put a `reset` around the block that contains
>>>> the invocation of `sleep`. This defines the boundaries of the
>>>> continuation context that you are saving inside `sleep` (or any
>>>> other method that captures the current continuation).
>>>>
>>>> The actual continuation is captured by `proceed` which is called
>>>> inside `sleep. It is used to extend the closure saved by `react`
>>>> with the current continuation up to the next enclosing `reset`.
>>>> Note that all code that uses continuation-capturing methods must
>>>> be `@suspendable`, i.e. transformed by the compiler plugin.
>>>>
>>>> The `proceed` utility function is defined in the `ActorUtils`
>>>> object:
>>>>
>>>> object ActorUtils {
>>>> def proceed[A, B](fun: PartialFunction[A, Unit] => Nothing):
>>>> PartialFunction[A, B] => B @cps[Unit, Unit] =
>>>> (caseBlock: PartialFunction[A, B]) =>
>>>> shift[B, Unit, Unit]((k: B => Unit) => fun(caseBlock
>>>> andThen k))
>>>> }
>>>>
>>>> Basically, what this function does is it takes a closure-saving
>>>> function, such as `react`, and turns it into a function that
>>>> takes a block of cases (`caseBlock`), just like `react`, except
>>>> that `caseBlock` has a result type `B`, since we can continue
>>>> processing a value of that type. `shift` captures the current
>>>> continuation, and invokes its argument function with it. In this
>>>> case we call the original closure-saving function (`react`), but
>>>> with a closure that is extended with the continuation (we pass
>>>> the continuation into `react`).
>>>>
>>>> The performance of this approach should be comparable to Kilim.
>>>> However, keep in mind that Scala's actors have many more
>>>> features than Kilim (such as message pattern matching,
>>>> `Actor.self`, implicit sender ID, threads interop, and actor
>>>> links) which currently lead to a certain overhead. It is not
>>>> easy to implement these features without paying for it.
>>>> I am not sure whether Kilim uses Lea's FJTask framework like
>>>> Scala's actors. It is faster than using a standard Java 5
>>>> executor, since it avoids a central queue for incoming tasks.
>>>>
>>>> Cheers,
>>>> Philipp
>>>>
>>>>
>>>> Sciss wrote:
>>>>> ok, thanks for the example. but isn't react particularly
>>>>> synchronous, "detaching" the actor instead of "suspending" it,
>>>>> and not asynchronous?
>>>>> i am in fact looking for a synchronous thing, to create
>>>>> cooperative multitasking (coroutines).
>>>>> i'm looking into kilim in this moment, see if i can get it to
>>>>> weave on top of my scala bytecode. the performance seems
>>>>> interesting, and the author mentions somewhere that it would
>>>>> be easy to write a custom scheduler to allow logical time
>>>>> advancing, which is exactly what i'm looking after....
>>>>> cheers, -sciss-
>>>>> Am 13.02.2009 um 12:07 schrieb Rich Dougherty:
>>>>>> On Fri, Feb 13, 2009 at 2:54 PM, Sciss wrote:
>>>>>>> isn't there a way to implement the sleep method that it can
>>>>>>> determine the
>>>>>>> current execution context / continuation, and then throught the
>>>>>>> SuspendActorException, so that execution is resumed with
>>>>>>> println ( "B" )....
>>>>>>> ? is there any way to hide the andThen chains and the
>>>>>>> necessity to nest
>>>>>>> functions inside functions?
>>>>>> There's no automatic way you can do it, but you can avoid
>>>>>> andThen and
>>>>>> nesting by using a for loop's syntactic sugar. See for example
>>>>>> Responder.
>>>>>>
>>>>>> http://scala.sygneca.com/libs/responder
>>>>>> http://www.scala-lang.org/docu/files/api/scala/Responder.html
>>>>>>
>>>>>> I have done a similar thing for linking together asynchronous
>>>>>> operations (like react). Below is an example that uses react
>>>>>> to get
>>>>>> two numbers, then sends the result to another actor. The
>>>>>> functions
>>>>>> "areact" and "async0" create AsyncFunctions - functions that
>>>>>> return
>>>>>> their result asynchronously. These are joined together by the
>>>>>> for loop
>>>>>> into a big AsyncFunction. The whole thing is then executed
>>>>>> with the
>>>>>> "->" operator and the result sent to the continuation created
>>>>>> by the
>>>>>> "fc0" method.
>>>>>>
>>>>>> (for (
>>>>>> x <- areact { case i: Int => i };
>>>>>> _ <- async0 { println("Received " + x) };
>>>>>> y <- areact { case i: Int => i };
>>>>>> _ <- async0 { println("Received " + y) };
>>>>>> _ <- async0 { caller ! (x + y) })
>>>>>> yield ()) -> fc0(())(thrower)
>>>>>>
>>>>>> Here's your sleep example, written another way:
>>>>>>
>>>>>> (for (
>>>>>> _ <- async0 { println("A") };
>>>>>> _ <- asleep(666);
>>>>>> _ <- async0 { println("B") })
>>>>>> yield ()).toFunction.apply
>>>>>>
>>>>>> In this case, instead of sending the result to a continuation
>>>>>> with the
>>>>>> "->" operator, I convert the AsyncFunction into a synchronous
>>>>>> Function0, and apply it directly.
>>>>>>
>>>>>> The for loop syntax is not pretty - I don't know if it's much
>>>>>> better
>>>>>> than using andThen! But if you're interested, you can see the
>>>>>> implementation of AsyncFunctions in the "controlflow" module
>>>>>> of Scala
>>>>>> OTP.
>>>>>>
>>>>>> http://github.com/richdougherty/scala-otp
>>>>>>
>>>>>> Cheers
>>>>>> Rich
>>>>>>
>>>>>> --
>>>>>> http://www.richdougherty.com/
>>>>
>>>
>>
>

Alex Cruise
Joined: 2008-12-17,
User offline. Last seen 2 years 26 weeks ago.
Re: Actors: Creating a continuation context

Sciss wrote:
> jesus, why is it's so complicated to get a very simple behaviour. is
> the scala.continuations only a bad hack that works in a few cases but
> fails in many other cases?
It's an undocumented, unreleased compiler plugin. :) If you're lucky,
Messrs. Haller or Rompf may be able to spare some time and draw you a
map of this uncharted territory on the back of a napkin. :)

-0xe1a

Tiark Rompf
Joined: 2009-02-18,
User offline. Last seen 42 years 45 weeks ago.
Re: Actors: Creating a continuation context
Hi all,

sorry for dropping in late to the discussion. Let me clarify some things about the status of continuations in Scala first. As people have noticed, the continuations plugin has not yet been officially released and we haven't invested much work into usability and documentation yet. It is currently in a state where we at EPFL work on getting the core functionality right and look for ways to improve libraries (Actors, ScalaFX, ...) by making parts of them use continuations internally.

That said, the continuations plugin is certainly more than a bad hack that works in only few cases, but it's true that it is not 100% transparent. For example, it doesn't allow you to capture continuations in some places. One admittedly annoying limitation that you encountered, Sciss, (and which we will work hard to support) is loops.

As  a workaround for the moment, you can define your own continuation-aware looping constructs:

 def loopWhile(cond: =>Boolean)(body: =>(Unit @suspendable)): Unit @suspendable = {
   if (cond) {
     body loopWhile(cond)(body)
   } else ()
 }

Another limitation (for the moment) is that every if-expression that includes transformed code (like sleep) in its then part must also have an else part.

Regarding performance, code that captures its continuation is transformed into continuation-passing style, wrapping the code that constitutes the continuation into an anonymous function (the continuation reaches as far as the nearest enclosing reset).  So performance is as good or bad as would be for an implementation using explicit closures. Since you mention Kilim, we haven't done a comprehensive comparative analysis yet, but in those cases we have compared, we were quite a bit faster (using pure continuations without Actors).

Note that if you're after utmost performance and don't need the functionality of the full Actor framework, you can also implement sleeping directly using standard Java Timers:

 import java.util.{Timer,TimerTask}

 val timer = new Timer()

 def sleep(delay: Int) = shift { k: (Unit => Unit) =>
   timer.schedule(new TimerTask {
     def run() = k()
   }, delay)
 }

 var count = 15
 reset {
   println("start")
   loopWhile(count != 0) {
     sleep(500)
     println("the time is: " + System.currentTimeMillis())
     count -= 1
   }
   println("end")
 }

In practice though, it would be a good idea to offload calling k() to a thread pool, so as not to bog down the timer's background thread.

Summing up, expressing code like yours elegantly was the major motivation for developing the continuations plugin, and even though it is pre-release software, it is not in a particularly immature or buggy state. Note that implementing continuations on the JVM is not a piece of cake and we're innovating in several aspects here. There remain some limitations to the use of continuations but the plugin won't randomly crash the compiler and it captures a lot of errors during type checking (with, admittedly a bit mysterious messages) that would otherwise lead to misbehaving code at runtime.

We'll work hard to get things into a releasable state soon, as support for continuations is scheduled for inclusion in Scala 2.8.0. Especially documentation is still lacking, and since class or method names might change, too, we cannot positively encourage you to use it for anything 'real' yet. But if you want to give it a try, we're happy to help where we can and we're eager to get feedback on which things still need to be improved. So it's your chance to ride the cutting edge ;-)

Cheers,
- Tiark

On 18.02.2009, at 00:54:15, Sciss wrote:

....unfortunately there is more problems. this works:

        fork {
         sleep( 666 )
          println( "step" )
          sleep( 1000 )
          println( "done" )
        }

this doesn't:

        fork {
          for( i <- (0 until 10) ) { ... }
            println( "i = " + i )
            sleep( 500 )
          }
          println( "done" )
        }

// ---> polymorphic expression cannot be instantiated to expected
type; found   : [C]de.sciss.tint.sc.Routine[Unit,C]  required: Unit
?

but it compiles if i do

        fork {
          for( i <- (0 until 10) ) { ... }
            println( "i = " + i )
            sleep( 500 )
          }
          sleep( 1000 )
          println( "done" )
        }

// ---> but the sleep( 500 ) statements don't have any effect, code
doesn't pause ;-(

trying to exchange for a 'while' loop:

        fork {
          var i = 0
          while( i < 10 ) {
            println( "i = " + i )
            sleep( 500 )
            i = i + 1
          }
          sleep( 1000 )
          println( "done" )
        }

// ---> found cps expression in non-cps position
// --->then and else parts must both be cps code or neither of them
?

jesus, why is it's so complicated to get a very simple behaviour. is
the scala.continuations only a bad hack that works in a few cases but
fails in many other cases? or can the desired behaviour be achieved?

thanks once more (sorry for the posting frequency...),

-sciss-



p.s. here's the missing code

class Routine[A,C]( val clock: Clock, ctx: => (A @cps[ A, C ]))
extends Actor {
  def act {
    reset( ctx )
  }

  private def proceed[A, B](fun: PartialFunction[A, Unit] => Nothing):
    PartialFunction[A, B] => B @cps[Unit, Unit] =
      (caseBlock: PartialFunction[A, B]) =>
           shift[B, Unit, Unit]((k: B => Unit) => fun(caseBlock
andThen k))

  def sleep(delta: Long): Unit @suspendable = {
    clock ! Reschedule( delta, self )
    proceed( react ) { case Awake => }
  }
}

  def fork[A,C]( ctx: =>(A @cps[A,C]) ) = { val r = new Routine
( Clock.default, ctx ); r.start; r }
  def sleep( delta: Long ): Unit @suspendable = self.asInstanceOf
[Routine[_,_]].sleep( delta )



Am 17.02.2009 um 18:59 schrieb Sciss:

yippieee, seems to work...

def sleep(delta: Long): Unit @suspendable = {
  sched ! Reschedule( 1000, self )
  proceed (react) { case Awake => println("Awoken") }
}

thanks a bunch philipp, will try to continue this trail.


Am 17.02.2009 um 18:50 schrieb Sciss:

ok.... sorry i should have read more carefully. so i copied and
pasted your 'proceed' method into my code. i managed to compile
and run from the command line (still don't know how to add the
compiler-plugin to needbeans). so... i guess to make your example
release sleep for awhile i would take out "self ! 'Awake" and
instead send a message to the scheduler. will try that out.

anyway, question remains if there is any documentation about
scala.continuations, since this is pretty difficult for me to
understand.

thanks, -sciss-


Am 17.02.2009 um 17:26 schrieb Sciss:

hi,

thank you for the link to this project. regarding your example, i
cannot find any information about your ActorUtils import. i
imported scala.actors.Actor._ and
scala.continuations.ControlContext._ instead. However, scalac
cannot deal with the "proceed" statement, so i'm unable to
compile this. also can you give me a link to the documentation of
scala.continuations, google didn't give me anything useful and
the examples are not commented.

thanks! ciao, -sciss-


object Sleep {
//  import ActorUtils._
import scala.actors.Actor._
import scala.continuations.ControlContext._

def sleep(delta: Long): Unit @suspendable = {
  self ! 'Awake
  proceed (react) { case 'Awake => println("Awoken") }  //
proceed is unknown .... where is it defined??
}

def main(args: Array[String]) {
  actor {
    reset {
      println("A")
      sleep(1000)
      println("B")
    }
  }
}
}


Am 16.02.2009 um 15:36 schrieb Philipp Haller:

Hi,

There is another possibility using a Scala compiler plugin for
delimited continuations created by Tiark Rompf. Currently, it
lives in the Scala SVN under

http://lampsvn.epfl.ch/trac/scala/browser/compiler-plugins/
continuations/trunk

Using this plugin your actor code can be written as follows
(sleeping code simplified):

object Sleep {
import ActorUtils._

def sleep(delta: Long): Unit @suspendable = {
  self ! 'Awake
  proceed (react) { case 'Awake => println("Awoken") }
}

def main(args: Array[String]) {
  actor {
    reset {
      println("A")
      sleep(1000)
      println("B")
    }
  }
}
}

Note that I have put a `reset` around the block that contains
the invocation of `sleep`. This defines the boundaries of the
continuation context that you are saving inside `sleep` (or any
other method that captures the current continuation).

The actual continuation is captured by `proceed` which is called
inside `sleep. It is used to extend the closure saved by `react`
with the current continuation up to the next enclosing `reset`.
Note that all code that uses continuation-capturing methods must
be `@suspendable`, i.e. transformed by the compiler plugin.

The `proceed` utility function is defined in the `ActorUtils`
object:

object ActorUtils {
def proceed[A, B](fun: PartialFunction[A, Unit] => Nothing):
  PartialFunction[A, B] => B @cps[Unit, Unit] =
    (caseBlock: PartialFunction[A, B]) =>
      shift[B, Unit, Unit]((k: B => Unit) => fun(caseBlock
andThen k))
}

Basically, what this function does is it takes a closure-saving
function, such as `react`, and turns it into a function that
takes a block of cases (`caseBlock`), just like `react`, except
that `caseBlock` has a result type `B`, since we can continue
processing a value of that type. `shift` captures the current
continuation, and invokes its argument function with it. In this
case we call the original closure-saving function (`react`), but
with a closure that is extended with the continuation (we pass
the continuation into `react`).

The performance of this approach should be comparable to Kilim.
However, keep in mind that Scala's actors have many more
features than Kilim (such as message pattern matching,
`Actor.self`, implicit sender ID, threads interop, and actor
links) which currently lead to a certain overhead. It is not
easy to implement these features without paying for it.
I am not sure whether Kilim uses Lea's FJTask framework like
Scala's actors. It is faster than using a standard Java 5
executor, since it avoids a central queue for incoming tasks.

Cheers,
Philipp


Sciss wrote:
ok, thanks for the example. but isn't react particularly
synchronous,  "detaching" the actor instead of "suspending" it,
and not asynchronous?
i am in fact looking for a synchronous thing, to create
cooperative  multitasking (coroutines).
i'm looking into kilim in this moment, see if i can get it to
weave  on top of my scala bytecode. the performance seems
interesting, and  the author mentions somewhere that it would
be easy to write a custom  scheduler to allow logical time
advancing, which is exactly what i'm  looking after....
cheers, -sciss-
Am 13.02.2009 um 12:07 schrieb Rich Dougherty:
On Fri, Feb 13, 2009 at 2:54 PM, Sciss <contact@sciss.de> wrote:
isn't there a way to implement the sleep method that it can
determine the
current execution context / continuation, and then throught the
SuspendActorException, so that execution is resumed with
println ( "B" )....
? is there any way to hide the andThen chains and the
necessity to  nest
functions inside functions?
There's no automatic way you can do it, but you can avoid
andThen and
nesting by using a for loop's syntactic sugar. See for example
Responder.

http://scala.sygneca.com/libs/responder
http://www.scala-lang.org/docu/files/api/scala/Responder.html

I have done a similar thing for linking together asynchronous
operations (like react). Below is an example that uses react
to get
two numbers, then sends the result to another actor. The
functions
"areact" and "async0" create AsyncFunctions - functions that
return
their result asynchronously. These are joined together by the
for loop
into a big AsyncFunction. The whole thing is then executed
with the
"->" operator and the result sent to the continuation created
by the
"fc0" method.

    (for (
      x <- areact { case i: Int => i };
      _ <- async0 { println("Received " + x) };
      y <- areact { case i: Int => i };
      _ <- async0 { println("Received " + y) };
      _ <- async0 { caller ! (x + y) })
      yield ()) -> fc0(())(thrower)

Here's your sleep example, written another way:

  (for (
    _ <- async0 { println("A") };
    _ <- asleep(666);
    _ <- async0 { println("B") })
            yield ()).toFunction.apply

In this case, instead of sending the result to a continuation
with the
"->" operator, I convert the AsyncFunction into a synchronous
Function0, and apply it directly.

The for loop syntax is not pretty - I don't know if it's much
better
than using andThen! But if you're interested, you can see the
implementation of AsyncFunctions in the "controlflow" module
of Scala
OTP.

  http://github.com/richdougherty/scala-otp

Cheers
Rich

--
http://www.richdougherty.com/






Sciss
Joined: 2008-12-17,
User offline. Last seen 28 weeks 5 days ago.
Re: Re: Actors: Creating a continuation context

tiark, thanks for your reply. your workaround produces an error here

def loopWhile(cond: =>Boolean)(body: =>(Unit @suspendable)): Unit
@suspendable = {
if (cond) {
body loopWhile(cond)(body) // ! ERROR
} else ()
}

// --> value loopWhile is not a member of Unit
@scala.continuations.cps[Unit, Unit]

?

as for the java timers: eventually i need to advance the timer in
logical units, not based directly on System.currentTimeMillis, so i
use an extra scheduling actor.

thanks once more, -sciss-

Am 18.02.2009 um 16:04 schrieb Tiark Rompf:

> Hi all,
>
> sorry for dropping in late to the discussion. Let me clarify some
> things about the status of continuations in Scala first. As people
> have noticed, the continuations plugin has not yet been officially
> released and we haven't invested much work into usability and
> documentation yet. It is currently in a state where we at EPFL work
> on getting the core functionality right and look for ways to
> improve libraries (Actors, ScalaFX, ...) by making parts of them
> use continuations internally.
>
> That said, the continuations plugin is certainly more than a bad
> hack that works in only few cases, but it's true that it is not
> 100% transparent. For example, it doesn't allow you to capture
> continuations in some places. One admittedly annoying limitation
> that you encountered, Sciss, (and which we will work hard to
> support) is loops.
>
> As a workaround for the moment, you can define your own
> continuation-aware looping constructs:
>
> def loopWhile(cond: =>Boolean)(body: =>(Unit @suspendable)): Unit
> @suspendable = {
> if (cond) {
> body loopWhile(cond)(body)
> } else ()
> }
>
> Another limitation (for the moment) is that every if-expression
> that includes transformed code (like sleep) in its then part must
> also have an else part.
>
> Regarding performance, code that captures its continuation is
> transformed into continuation-passing style, wrapping the code that
> constitutes the continuation into an anonymous function (the
> continuation reaches as far as the nearest enclosing reset). So
> performance is as good or bad as would be for an implementation
> using explicit closures. Since you mention Kilim, we haven't done a
> comprehensive comparative analysis yet, but in those cases we have
> compared, we were quite a bit faster (using pure continuations
> without Actors).
>
> Note that if you're after utmost performance and don't need the
> functionality of the full Actor framework, you can also implement
> sleeping directly using standard Java Timers:
>
> import java.util.{Timer,TimerTask}
>
> val timer = new Timer()
>
> def sleep(delay: Int) = shift { k: (Unit => Unit) =>
> timer.schedule(new TimerTask {
> def run() = k()
> }, delay)
> }
>
> var count = 15
> reset {
> println("start")
> loopWhile(count != 0) {
> sleep(500)
> println("the time is: " + System.currentTimeMillis())
> count -= 1
> }
> println("end")
> }
>
> In practice though, it would be a good idea to offload calling k()
> to a thread pool, so as not to bog down the timer's background thread.
>
> Summing up, expressing code like yours elegantly was the major
> motivation for developing the continuations plugin, and even though
> it is pre-release software, it is not in a particularly immature or
> buggy state. Note that implementing continuations on the JVM is not
> a piece of cake and we're innovating in several aspects here. There
> remain some limitations to the use of continuations but the plugin
> won't randomly crash the compiler and it captures a lot of errors
> during type checking (with, admittedly a bit mysterious messages)
> that would otherwise lead to misbehaving code at runtime.
>
> We'll work hard to get things into a releasable state soon, as
> support for continuations is scheduled for inclusion in Scala
> 2.8.0. Especially documentation is still lacking, and since class
> or method names might change, too, we cannot positively encourage
> you to use it for anything 'real' yet. But if you want to give it a
> try, we're happy to help where we can and we're eager to get
> feedback on which things still need to be improved. So it's your
> chance to ride the cutting edge ;-)
>
> Cheers,
> - Tiark
>
> On 18.02.2009, at 00:54:15, Sciss wrote:
>
>> ....unfortunately there is more problems. this works:
[...]

Tiark Rompf
Joined: 2009-02-18,
User offline. Last seen 42 years 45 weeks ago.
Re: Re: Actors: Creating a continuation context

Apparently I screwed up the formatting when pasting the code (sorry
about that).
There's a newline (or semicolon) missing:

def loopWhile(cond: =>Boolean)(body: =>(Unit @suspendable)): Unit
@suspendable = {
if (cond) {
body
loopWhile(cond)(body)
} else ()
}

- Tiark

On 18.02.2009, at 16:48, Sciss wrote:

> tiark, thanks for your reply. your workaround produces an error here
>
> def loopWhile(cond: =>Boolean)(body: =>(Unit @suspendable)): Unit
> @suspendable = {
> if (cond) {
> body loopWhile(cond)(body) // ! ERROR
> } else ()
> }
>
> // --> value loopWhile is not a member of Unit
> @scala.continuations.cps[Unit, Unit]
>
> ?
>
> as for the java timers: eventually i need to advance the timer in
> logical units, not based directly on System.currentTimeMillis, so i
> use an extra scheduling actor.
>
> thanks once more, -sciss-
>
>
> Am 18.02.2009 um 16:04 schrieb Tiark Rompf:
>
>> Hi all,
>>
>> sorry for dropping in late to the discussion. Let me clarify some
>> things about the status of continuations in Scala first. As people
>> have noticed, the continuations plugin has not yet been officially
>> released and we haven't invested much work into usability and
>> documentation yet. It is currently in a state where we at EPFL work
>> on getting the core functionality right and look for ways to
>> improve libraries (Actors, ScalaFX, ...) by making parts of them
>> use continuations internally.
>>
>> That said, the continuations plugin is certainly more than a bad
>> hack that works in only few cases, but it's true that it is not
>> 100% transparent. For example, it doesn't allow you to capture
>> continuations in some places. One admittedly annoying limitation
>> that you encountered, Sciss, (and which we will work hard to
>> support) is loops.
>>
>> As a workaround for the moment, you can define your own
>> continuation-aware looping constructs:
>>
>> def loopWhile(cond: =>Boolean)(body: =>(Unit @suspendable)): Unit
>> @suspendable = {
>> if (cond) {
>> body loopWhile(cond)(body)
>> } else ()
>> }
>>
>> Another limitation (for the moment) is that every if-expression
>> that includes transformed code (like sleep) in its then part must
>> also have an else part.
>>
>> Regarding performance, code that captures its continuation is
>> transformed into continuation-passing style, wrapping the code that
>> constitutes the continuation into an anonymous function (the
>> continuation reaches as far as the nearest enclosing reset). So
>> performance is as good or bad as would be for an implementation
>> using explicit closures. Since you mention Kilim, we haven't done a
>> comprehensive comparative analysis yet, but in those cases we have
>> compared, we were quite a bit faster (using pure continuations
>> without Actors).
>>
>> Note that if you're after utmost performance and don't need the
>> functionality of the full Actor framework, you can also implement
>> sleeping directly using standard Java Timers:
>>
>> import java.util.{Timer,TimerTask}
>>
>> val timer = new Timer()
>>
>> def sleep(delay: Int) = shift { k: (Unit => Unit) =>
>> timer.schedule(new TimerTask {
>> def run() = k()
>> }, delay)
>> }
>>
>> var count = 15
>> reset {
>> println("start")
>> loopWhile(count != 0) {
>> sleep(500)
>> println("the time is: " + System.currentTimeMillis())
>> count -= 1
>> }
>> println("end")
>> }
>>
>> In practice though, it would be a good idea to offload calling k()
>> to a thread pool, so as not to bog down the timer's background
>> thread.
>>
>> Summing up, expressing code like yours elegantly was the major
>> motivation for developing the continuations plugin, and even though
>> it is pre-release software, it is not in a particularly immature or
>> buggy state. Note that implementing continuations on the JVM is not
>> a piece of cake and we're innovating in several aspects here. There
>> remain some limitations to the use of continuations but the plugin
>> won't randomly crash the compiler and it captures a lot of errors
>> during type checking (with, admittedly a bit mysterious messages)
>> that would otherwise lead to misbehaving code at runtime.
>>
>> We'll work hard to get things into a releasable state soon, as
>> support for continuations is scheduled for inclusion in Scala
>> 2.8.0. Especially documentation is still lacking, and since class
>> or method names might change, too, we cannot positively encourage
>> you to use it for anything 'real' yet. But if you want to give it a
>> try, we're happy to help where we can and we're eager to get
>> feedback on which things still need to be improved. So it's your
>> chance to ride the cutting edge ;-)
>>
>> Cheers,
>> - Tiark
>>
>> On 18.02.2009, at 00:54:15, Sciss wrote:
>>
>>> ....unfortunately there is more problems. this works:
> [...]
>
>

Rich Dougherty 2
Joined: 2009-01-19,
User offline. Last seen 42 years 45 weeks ago.
Re: Re: Actors: Creating a continuation context

On Thu, Feb 19, 2009 at 4:04 AM, Tiark Rompf wrote:
> Summing up, expressing code like yours elegantly was the major motivation
> for developing the continuations plugin, [...]
>
> We'll work hard to get things into a releasable state soon, as support
> for continuations is scheduled for inclusion in Scala 2.8.0. Especially
> documentation is still lacking, and since class or method names might
> change, too, we cannot positively encourage you to use it for anything
> 'real' yet. But if you want to give it a try, we're happy to help where we
> can and we're eager to get feedback on which things still need to be
> improved. So it's your chance to ride the cutting edge ;-)

Hi Tiark

This is very exciting for me. I've been rolling my own "continuations"
for doing async IO work for the past few months, and it would be
really great to have an automatic translation. I've read through some
of the plugin's source. Next week I should be able to actually
download it and try it out.

Here's a question for you. Do you plan on adding support for
exceptions? Real Scala computations can can continue either by
yielding a result or throwing an exception, so it would be great to be
able to handle both of these possibilities. For example, in the IO
work I'm doing there could be an IOException at any point and it is
necessary to handle these exceptions to ensure resources are closed
properly, etc.

To clarify what I mean, here's an interface for code that wants to be
"exception aware". I've been working with code like this myself, it's
not too difficult to emulate finally and catch clauses - although you
might have to live with confusing behaviour, like finally clauses
being able to run multiple times.

def shiftEither(fun: (Either[Throwable,A] => B) => C): A @cps[B,C] /* ?? */ = {
throw new NoSuchMethodException("this code has to be compiled with
the scala CPS plugin")
}

The above method is more general than the current interface which
handles only normal returns, as shown below.

def shift[A,B,C](fun: (A => B) => C): A @cps[B,C] = {
shiftWithException { k: (Either[Throwable,A] => B) =>
fun { a: A => k(Right(a)) }
}
}

Even without exception support, this is terrific work. Out of
interest, are you interested in contributions, or is it a solo effort
for the moment?

Cheers
Rich

Copyright © 2012 École Polytechnique Fédérale de Lausanne (EPFL), Lausanne, Switzerland