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

design goals of actors library

10 replies
Erik Engbrecht
Joined: 2008-12-19,
User offline. Last seen 3 years 18 weeks ago.
Snipped from ESME mailing list:
More broadly, there's a discussion going on on scala-internals about what
can be done about Actors for Scala 2.8.  There are a lot of people
addressing the issue.  I have a high degree of confidence that they will get
to a reasonable solution for Scala's Actor library.  However, Scala's Actors
seem to be very heavy weight for what most apps I build (including ESME)
need.  I've been noodling with the idea of writing a very light weight Actor
library so that Lift has more control over this escential part of
interactive apps.

David,  Could you elaborate a bit on what your design goals/requirements would be if you were to build your own actors library for lift?  I think it would be a good datapoint for those of us thinking about solutions to the various issues that the library has.
-Erik
David Pollak
Joined: 2008-12-16,
User offline. Last seen 42 years 45 weeks ago.
Re: design goals of actors library
Erik,

Here's the Actor class that I build.  It's a thing that has a mailbox and executes the stuff in its mailbox asynchronously from the act of putting stuff in its mailbox with the exception that if it's running in single threaded mode (for GAE), it does work-stealing.

The only state is "is there a thread that's servicing the mailbox" and "the mailbox".

I have a separate "Futures" class that allows for the concept of a "send and receive", but the future is included in the message.

The whole idea is that everything is *very* lightweight and the level of complexity is very low.

Thanks,

David

PS -- Please see the enclosed code

On Fri, May 22, 2009 at 11:24 AM, Erik Engbrecht <erik.engbrecht@gmail.com> wrote:
Snipped from ESME mailing list:
More broadly, there's a discussion going on on scala-internals about what
can be done about Actors for Scala 2.8.  There are a lot of people
addressing the issue.  I have a high degree of confidence that they will get
to a reasonable solution for Scala's Actor library.  However, Scala's Actors
seem to be very heavy weight for what most apps I build (including ESME)
need.  I've been noodling with the idea of writing a very light weight Actor
library so that Lift has more control over this escential part of
interactive apps.

David,  Could you elaborate a bit on what your design goals/requirements would be if you were to build your own actors library for lift?  I think it would be a good datapoint for those of us thinking about solutions to the various issues that the library has.
-Erik

/*
 * Copyright 2009 WorldWide Conferencing, LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 */

package net.liftweb.actor

import util._
import Helpers._

trait IExecute {
  def execute(f: () => Unit): Unit
  def shutdown(): Unit
}

object Scheduler {
  @volatile
  var onSameThread = false

  @volatile
  var createExecutor: () => IExecute = () => {
    new IExecute {
      import java.util.concurrent.{Executors, Executor}

      private val es: Executor = Executors.newCachedThreadPool()

      def execute(f: () => Unit): Unit =
      es.execute(new Runnable{def run() {f()}})


      def shutdown(): Unit = {}
    }
  }

  @volatile
  var exec: IExecute = _

  def execute(f: () => Unit) {touch; exec.execute(f)}

  private lazy val touch = {
    exec = createExecutor()
    true
  }
}

private[actor] trait IMailboxItem[T] {
  protected var next: IMailboxItem[T] = _
  protected var prev: IMailboxItem[T] = _

  private[actor] def find(f: IMailboxItem[T] => Boolean): Box[IMailboxItem[T]] =
  if (f(this)) Full(this) else next.find(f)

  private[actor] def remove() {
    val newPrev = prev
    prev.next = next
    next.prev = prev
  }

  private[actor] def insertAfter(newItem: IMailboxItem[T]) {
    next.prev = newItem
    newItem.prev = this
    newItem.next = this.next
    next = newItem
  }

  private[actor] def insertBefore(newItem: IMailboxItem[T]) {
    prev.next = newItem
    newItem.prev = this.prev
    newItem.next = this
    prev = newItem
  }

  def item: T
}

private[actor] class MailboxItem[T](val item: T) extends IMailboxItem[T]

trait SpecializeActor[T] extends IMailboxItem[T] {
  private var processing = false

  def !(msg: T): Unit = {
    val toDo: () => Unit = synchronized {
      addToMailbox(msg)
      if (!processing) {
        if (Scheduler.onSameThread) {
          processing = true
          () => processMailbox(true)
        } else {
          Scheduler.execute(() => processMailbox(false))
          () => {}
        }
      }
      else () => {}
    }
    toDo()
  }

  private def addToMailbox(msg: T): Unit = synchronized {
    this.insertBefore(new MailboxItem(msg))
  }

  private def processMailbox(ignoreProcessing: Boolean) {
    val eh =
    synchronized {
      if (!ignoreProcessing && processing) return
      processing = true
      exceptionHandler
    }
    try {
      var done = false
      while (!done) {
        val pf = messageHandler
        synchronized{next.find(v => pf.isDefinedAt(v.item))} match {
          case Full(mb) =>
            synchronized {
              mb.remove()
            }
            try {
              pf(mb.item)
            } catch {
              case e: Exception => if (eh.isDefinedAt(e)) eh(e)
            }
          case _ => done = false
        }
      }
    } catch {
      case e =>
        if (eh.isDefinedAt(e)) eh(e)
        throw e
    } finally {
      synchronized {
        processing = false
      }
    }
  }

  override private[actor] def find(f: IMailboxItem[T] => Boolean): Box[IMailboxItem[T]] =
  Empty

  protected def messageHandler: PartialFunction[T, Unit]

  protected def exceptionHandler: PartialFunction[Throwable, Unit] = Map()

  private def ctor() {
    next = this
    prev = this
  }
}

trait Actor extends SpecializeActor[Any]


--
Lift, the simply functional web framework http://liftweb.net
Beginning Scala http://www.apress.com/book/view/1430219890
Follow me: http://twitter.com/dpp
Git some: http://github.com/dpp
Erik Engbrecht
Joined: 2008-12-19,
User offline. Last seen 3 years 18 weeks ago.
Re: design goals of actors library
David,  Thanks!  There's one thing that really confuses me.  Why did you model the actor/mailbox relationship using inheritance instead of composition?
-Erik

On Fri, May 22, 2009 at 3:16 PM, David Pollak <feeder.of.the.bears@gmail.com> wrote:
Erik,

Here's the Actor class that I build.  It's a thing that has a mailbox and executes the stuff in its mailbox asynchronously from the act of putting stuff in its mailbox with the exception that if it's running in single threaded mode (for GAE), it does work-stealing.

The only state is "is there a thread that's servicing the mailbox" and "the mailbox".

I have a separate "Futures" class that allows for the concept of a "send and receive", but the future is included in the message.

The whole idea is that everything is *very* lightweight and the level of complexity is very low.

Thanks,

David

PS -- Please see the enclosed code

On Fri, May 22, 2009 at 11:24 AM, Erik Engbrecht <erik.engbrecht@gmail.com> wrote:
Snipped from ESME mailing list:
More broadly, there's a discussion going on on scala-internals about what
can be done about Actors for Scala 2.8.  There are a lot of people
addressing the issue.  I have a high degree of confidence that they will get
to a reasonable solution for Scala's Actor library.  However, Scala's Actors
seem to be very heavy weight for what most apps I build (including ESME)
need.  I've been noodling with the idea of writing a very light weight Actor
library so that Lift has more control over this escential part of
interactive apps.

David,  Could you elaborate a bit on what your design goals/requirements would be if you were to build your own actors library for lift?  I think it would be a good datapoint for those of us thinking about solutions to the various issues that the library has.
-Erik

/*
 * Copyright 2009 WorldWide Conferencing, LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 */

package net.liftweb.actor

import util._
import Helpers._

trait IExecute {
  def execute(f: () => Unit): Unit
  def shutdown(): Unit
}

object Scheduler {
  @volatile
  var onSameThread = false

  @volatile
  var createExecutor: () => IExecute = () => {
    new IExecute {
      import java.util.concurrent.{Executors, Executor}

      private val es: Executor = Executors.newCachedThreadPool()

      def execute(f: () => Unit): Unit =
      es.execute(new Runnable{def run() {f()}})


      def shutdown(): Unit = {}
    }
  }

  @volatile
  var exec: IExecute = _

  def execute(f: () => Unit) {touch; exec.execute(f)}

  private lazy val touch = {
    exec = createExecutor()
    true
  }
}

private[actor] trait IMailboxItem[T] {
  protected var next: IMailboxItem[T] = _
  protected var prev: IMailboxItem[T] = _

  private[actor] def find(f: IMailboxItem[T] => Boolean): Box[IMailboxItem[T]] =
  if (f(this)) Full(this) else next.find(f)

  private[actor] def remove() {
    val newPrev = prev
    prev.next = next
    next.prev = prev
  }

  private[actor] def insertAfter(newItem: IMailboxItem[T]) {
    next.prev = newItem
    newItem.prev = this
    newItem.next = this.next
    next = newItem
  }

  private[actor] def insertBefore(newItem: IMailboxItem[T]) {
    prev.next = newItem
    newItem.prev = this.prev
    newItem.next = this
    prev = newItem
  }

  def item: T
}

private[actor] class MailboxItem[T](val item: T) extends IMailboxItem[T]

trait SpecializeActor[T] extends IMailboxItem[T] {
  private var processing = false

  def !(msg: T): Unit = {
    val toDo: () => Unit = synchronized {
      addToMailbox(msg)
      if (!processing) {
        if (Scheduler.onSameThread) {
          processing = true
          () => processMailbox(true)
        } else {
          Scheduler.execute(() => processMailbox(false))
          () => {}
        }
      }
      else () => {}
    }
    toDo()
  }

  private def addToMailbox(msg: T): Unit = synchronized {
    this.insertBefore(new MailboxItem(msg))
  }

  private def processMailbox(ignoreProcessing: Boolean) {
    val eh =
    synchronized {
      if (!ignoreProcessing && processing) return
      processing = true
      exceptionHandler
    }
    try {
      var done = false
      while (!done) {
        val pf = messageHandler
        synchronized{next.find(v => pf.isDefinedAt(v.item))} match {
          case Full(mb) =>
            synchronized {
              mb.remove()
            }
            try {
              pf(mb.item)
            } catch {
              case e: Exception => if (eh.isDefinedAt(e)) eh(e)
            }
          case _ => done = false
        }
      }
    } catch {
      case e =>
        if (eh.isDefinedAt(e)) eh(e)
        throw e
    } finally {
      synchronized {
        processing = false
      }
    }
  }

  override private[actor] def find(f: IMailboxItem[T] => Boolean): Box[IMailboxItem[T]] =
  Empty

  protected def messageHandler: PartialFunction[T, Unit]

  protected def exceptionHandler: PartialFunction[Throwable, Unit] = Map()

  private def ctor() {
    next = this
    prev = this
  }
}

trait Actor extends SpecializeActor[Any]


--
Lift, the simply functional web framework http://liftweb.net
Beginning Scala http://www.apress.com/book/view/1430219890
Follow me: http://twitter.com/dpp
Git some: http://github.com/dpp



--
http://erikengbrecht.blogspot.com/
David Pollak
Joined: 2008-12-16,
User offline. Last seen 42 years 45 weeks ago.
Re: design goals of actors library


On Fri, May 22, 2009 at 12:38 PM, Erik Engbrecht <erik.engbrecht@gmail.com> wrote:
David,  Thanks!  There's one thing that really confuses me.  Why did you model the actor/mailbox relationship using inheritance instead of composition?

IMailboxItem is a private[actor], so it should not appear as a public interface... it's an implementation detail to make the Actor part of the linked list that represents the internal mailbox state.
 

-Erik

On Fri, May 22, 2009 at 3:16 PM, David Pollak <feeder.of.the.bears@gmail.com> wrote:
Erik,

Here's the Actor class that I build.  It's a thing that has a mailbox and executes the stuff in its mailbox asynchronously from the act of putting stuff in its mailbox with the exception that if it's running in single threaded mode (for GAE), it does work-stealing.

The only state is "is there a thread that's servicing the mailbox" and "the mailbox".

I have a separate "Futures" class that allows for the concept of a "send and receive", but the future is included in the message.

The whole idea is that everything is *very* lightweight and the level of complexity is very low.

Thanks,

David

PS -- Please see the enclosed code

On Fri, May 22, 2009 at 11:24 AM, Erik Engbrecht <erik.engbrecht@gmail.com> wrote:
Snipped from ESME mailing list:
More broadly, there's a discussion going on on scala-internals about what
can be done about Actors for Scala 2.8.  There are a lot of people
addressing the issue.  I have a high degree of confidence that they will get
to a reasonable solution for Scala's Actor library.  However, Scala's Actors
seem to be very heavy weight for what most apps I build (including ESME)
need.  I've been noodling with the idea of writing a very light weight Actor
library so that Lift has more control over this escential part of
interactive apps.

David,  Could you elaborate a bit on what your design goals/requirements would be if you were to build your own actors library for lift?  I think it would be a good datapoint for those of us thinking about solutions to the various issues that the library has.
-Erik

/*
 * Copyright 2009 WorldWide Conferencing, LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 */

package net.liftweb.actor

import util._
import Helpers._

trait IExecute {
  def execute(f: () => Unit): Unit
  def shutdown(): Unit
}

object Scheduler {
  @volatile
  var onSameThread = false

  @volatile
  var createExecutor: () => IExecute = () => {
    new IExecute {
      import java.util.concurrent.{Executors, Executor}

      private val es: Executor = Executors.newCachedThreadPool()

      def execute(f: () => Unit): Unit =
      es.execute(new Runnable{def run() {f()}})


      def shutdown(): Unit = {}
    }
  }

  @volatile
  var exec: IExecute = _

  def execute(f: () => Unit) {touch; exec.execute(f)}

  private lazy val touch = {
    exec = createExecutor()
    true
  }
}

private[actor] trait IMailboxItem[T] {
  protected var next: IMailboxItem[T] = _
  protected var prev: IMailboxItem[T] = _

  private[actor] def find(f: IMailboxItem[T] => Boolean): Box[IMailboxItem[T]] =
  if (f(this)) Full(this) else next.find(f)

  private[actor] def remove() {
    val newPrev = prev
    prev.next = next
    next.prev = prev
  }

  private[actor] def insertAfter(newItem: IMailboxItem[T]) {
    next.prev = newItem
    newItem.prev = this
    newItem.next = this.next
    next = newItem
  }

  private[actor] def insertBefore(newItem: IMailboxItem[T]) {
    prev.next = newItem
    newItem.prev = this.prev
    newItem.next = this
    prev = newItem
  }

  def item: T
}

private[actor] class MailboxItem[T](val item: T) extends IMailboxItem[T]

trait SpecializeActor[T] extends IMailboxItem[T] {
  private var processing = false

  def !(msg: T): Unit = {
    val toDo: () => Unit = synchronized {
      addToMailbox(msg)
      if (!processing) {
        if (Scheduler.onSameThread) {
          processing = true
          () => processMailbox(true)
        } else {
          Scheduler.execute(() => processMailbox(false))
          () => {}
        }
      }
      else () => {}
    }
    toDo()
  }

  private def addToMailbox(msg: T): Unit = synchronized {
    this.insertBefore(new MailboxItem(msg))
  }

  private def processMailbox(ignoreProcessing: Boolean) {
    val eh =
    synchronized {
      if (!ignoreProcessing && processing) return
      processing = true
      exceptionHandler
    }
    try {
      var done = false
      while (!done) {
        val pf = messageHandler
        synchronized{next.find(v => pf.isDefinedAt(v.item))} match {
          case Full(mb) =>
            synchronized {
              mb.remove()
            }
            try {
              pf(mb.item)
            } catch {
              case e: Exception => if (eh.isDefinedAt(e)) eh(e)
            }
          case _ => done = false
        }
      }
    } catch {
      case e =>
        if (eh.isDefinedAt(e)) eh(e)
        throw e
    } finally {
      synchronized {
        processing = false
      }
    }
  }

  override private[actor] def find(f: IMailboxItem[T] => Boolean): Box[IMailboxItem[T]] =
  Empty

  protected def messageHandler: PartialFunction[T, Unit]

  protected def exceptionHandler: PartialFunction[Throwable, Unit] = Map()

  private def ctor() {
    next = this
    prev = this
  }
}

trait Actor extends SpecializeActor[Any]


--
Lift, the simply functional web framework http://liftweb.net
Beginning Scala http://www.apress.com/book/view/1430219890
Follow me: http://twitter.com/dpp
Git some: http://github.com/dpp



--
http://erikengbrecht.blogspot.com/



--
Lift, the simply functional web framework http://liftweb.net
Beginning Scala http://www.apress.com/book/view/1430219890
Follow me: http://twitter.com/dpp
Git some: http://github.com/dpp
milessabin
Joined: 2008-08-11,
User offline. Last seen 33 weeks 3 days ago.
Re: Re: design goals of actors library

On Fri, May 22, 2009 at 9:16 PM, David Pollak
wrote:
> Here's the Actor class that I build.  It's a thing that has a mailbox and
> executes the stuff in its mailbox asynchronously from the act of putting
> stuff in its mailbox with the exception that if it's running in single
> threaded mode (for GAE), it does work-stealing.
>
> The only state is "is there a thread that's servicing the mailbox" and "the
> mailbox".

To me it looks like a standard workqueue/workpile, so why not call it
that rather than risking confusion with Scala's actors (which are
aiming to be something a bit different)?

Cheers,

Miles

Erik Engbrecht
Joined: 2008-12-19,
User offline. Last seen 3 years 18 weeks ago.
Re: design goals of actors library
David,  Thank you for posting this.  It's given me some interesting ideas...   I'll post back later when I have some code.
-Erik

On Fri, May 22, 2009 at 3:42 PM, David Pollak <feeder.of.the.bears@gmail.com> wrote:


On Fri, May 22, 2009 at 12:38 PM, Erik Engbrecht <erik.engbrecht@gmail.com> wrote:
David,  Thanks!  There's one thing that really confuses me.  Why did you model the actor/mailbox relationship using inheritance instead of composition?

IMailboxItem is a private[actor], so it should not appear as a public interface... it's an implementation detail to make the Actor part of the linked list that represents the internal mailbox state.
 

-Erik

On Fri, May 22, 2009 at 3:16 PM, David Pollak <feeder.of.the.bears@gmail.com> wrote:
Erik,

Here's the Actor class that I build.  It's a thing that has a mailbox and executes the stuff in its mailbox asynchronously from the act of putting stuff in its mailbox with the exception that if it's running in single threaded mode (for GAE), it does work-stealing.

The only state is "is there a thread that's servicing the mailbox" and "the mailbox".

I have a separate "Futures" class that allows for the concept of a "send and receive", but the future is included in the message.

The whole idea is that everything is *very* lightweight and the level of complexity is very low.

Thanks,

David

PS -- Please see the enclosed code

On Fri, May 22, 2009 at 11:24 AM, Erik Engbrecht <erik.engbrecht@gmail.com> wrote:
Snipped from ESME mailing list:
More broadly, there's a discussion going on on scala-internals about what
can be done about Actors for Scala 2.8.  There are a lot of people
addressing the issue.  I have a high degree of confidence that they will get
to a reasonable solution for Scala's Actor library.  However, Scala's Actors
seem to be very heavy weight for what most apps I build (including ESME)
need.  I've been noodling with the idea of writing a very light weight Actor
library so that Lift has more control over this escential part of
interactive apps.

David,  Could you elaborate a bit on what your design goals/requirements would be if you were to build your own actors library for lift?  I think it would be a good datapoint for those of us thinking about solutions to the various issues that the library has.
-Erik

/*
 * Copyright 2009 WorldWide Conferencing, LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 */

package net.liftweb.actor

import util._
import Helpers._

trait IExecute {
  def execute(f: () => Unit): Unit
  def shutdown(): Unit
}

object Scheduler {
  @volatile
  var onSameThread = false

  @volatile
  var createExecutor: () => IExecute = () => {
    new IExecute {
      import java.util.concurrent.{Executors, Executor}

      private val es: Executor = Executors.newCachedThreadPool()

      def execute(f: () => Unit): Unit =
      es.execute(new Runnable{def run() {f()}})


      def shutdown(): Unit = {}
    }
  }

  @volatile
  var exec: IExecute = _

  def execute(f: () => Unit) {touch; exec.execute(f)}

  private lazy val touch = {
    exec = createExecutor()
    true
  }
}

private[actor] trait IMailboxItem[T] {
  protected var next: IMailboxItem[T] = _
  protected var prev: IMailboxItem[T] = _

  private[actor] def find(f: IMailboxItem[T] => Boolean): Box[IMailboxItem[T]] =
  if (f(this)) Full(this) else next.find(f)

  private[actor] def remove() {
    val newPrev = prev
    prev.next = next
    next.prev = prev
  }

  private[actor] def insertAfter(newItem: IMailboxItem[T]) {
    next.prev = newItem
    newItem.prev = this
    newItem.next = this.next
    next = newItem
  }

  private[actor] def insertBefore(newItem: IMailboxItem[T]) {
    prev.next = newItem
    newItem.prev = this.prev
    newItem.next = this
    prev = newItem
  }

  def item: T
}

private[actor] class MailboxItem[T](val item: T) extends IMailboxItem[T]

trait SpecializeActor[T] extends IMailboxItem[T] {
  private var processing = false

  def !(msg: T): Unit = {
    val toDo: () => Unit = synchronized {
      addToMailbox(msg)
      if (!processing) {
        if (Scheduler.onSameThread) {
          processing = true
          () => processMailbox(true)
        } else {
          Scheduler.execute(() => processMailbox(false))
          () => {}
        }
      }
      else () => {}
    }
    toDo()
  }

  private def addToMailbox(msg: T): Unit = synchronized {
    this.insertBefore(new MailboxItem(msg))
  }

  private def processMailbox(ignoreProcessing: Boolean) {
    val eh =
    synchronized {
      if (!ignoreProcessing && processing) return
      processing = true
      exceptionHandler
    }
    try {
      var done = false
      while (!done) {
        val pf = messageHandler
        synchronized{next.find(v => pf.isDefinedAt(v.item))} match {
          case Full(mb) =>
            synchronized {
              mb.remove()
            }
            try {
              pf(mb.item)
            } catch {
              case e: Exception => if (eh.isDefinedAt(e)) eh(e)
            }
          case _ => done = false
        }
      }
    } catch {
      case e =>
        if (eh.isDefinedAt(e)) eh(e)
        throw e
    } finally {
      synchronized {
        processing = false
      }
    }
  }

  override private[actor] def find(f: IMailboxItem[T] => Boolean): Box[IMailboxItem[T]] =
  Empty

  protected def messageHandler: PartialFunction[T, Unit]

  protected def exceptionHandler: PartialFunction[Throwable, Unit] = Map()

  private def ctor() {
    next = this
    prev = this
  }
}

trait Actor extends SpecializeActor[Any]


--
Lift, the simply functional web framework http://liftweb.net
Beginning Scala http://www.apress.com/book/view/1430219890
Follow me: http://twitter.com/dpp
Git some: http://github.com/dpp



--
http://erikengbrecht.blogspot.com/



--
Lift, the simply functional web framework http://liftweb.net
Beginning Scala http://www.apress.com/book/view/1430219890
Follow me: http://twitter.com/dpp
Git some: http://github.com/dpp



--
http://erikengbrecht.blogspot.com/
David Pollak
Joined: 2008-12-16,
User offline. Last seen 42 years 45 weeks ago.
Re: Re: design goals of actors library


On Fri, May 22, 2009 at 1:25 PM, Miles Sabin <miles@milessabin.com> wrote:
On Fri, May 22, 2009 at 9:16 PM, David Pollak
<feeder.of.the.bears@gmail.com> wrote:
> Here's the Actor class that I build.  It's a thing that has a mailbox and
> executes the stuff in its mailbox asynchronously from the act of putting
> stuff in its mailbox with the exception that if it's running in single
> threaded mode (for GAE), it does work-stealing.
>
> The only state is "is there a thread that's servicing the mailbox" and "the
> mailbox".

To me it looks like a standard workqueue/workpile, so why not call it
that rather than risking confusion with Scala's actors (which are
aiming to be something a bit different)?

I'm not sure if this is anything different than what I understand the Erlang Actor model formerly the Scheme Actor model to be... asynchronous message handling.

I think the Scala Actors have become something more than the original Actor model.
 


Cheers,


Miles

--
Miles Sabin
tel: +44 (0)7813 944 528
skype:  milessabin
http://twitter.com/milessabin



--
Lift, the simply functional web framework http://liftweb.net
Beginning Scala http://www.apress.com/book/view/1430219890
Follow me: http://twitter.com/dpp
Git some: http://github.com/dpp
Philipp Haller
Joined: 2009-01-13,
User offline. Last seen 42 years 45 weeks ago.
Re: Re: design goals of actors library

Hi all,

I played a little with the design of David's LiftActor. There are some
notable differences between LiftActor and scala.actors.Actor:

(a) LiftActor has a `messageHandler` that is always "enabled", as
opposed to `react` which is used to process only a single message.
`loop { react {...} }` is not treated specially in Actor.

(b) Moreover, `LiftActor`s are not started; they always accept messages.

Therefore, one could think that the two models are fundamentally
incompatible with each other. It turns out that this is not the case.

Scala's Actors only have to be started to execute the code in act()
before the first `react`. Upon hitting the first `react`, Actor and
LiftActor behave essentially the same except for (a).

So, the remaining question is: can we combine the always-enabled message
handler and `react` in the same model? I include below a proof of
concept `SimpleActor` implementation, which does just that. It has the
`messageHandler` from LiftActor, but also supports `react`. There are
some minor differences to LiftActor for integrating SimpleActor into
scala.actors. Another difference to LiftActor is that in the send method
we test on the sender's thread whether the SimpleActor can resume
processing because of a matching message.

If you want to give it a try, I include the ping pong example for
SimpleActor. However, note that this is just some experimental code. I
am not sure whether we should integrate something like this, or whether
the current design should be changed in any way. Something like
`exceptionHandler` could easily be integrated into scala.actors.Actor,
though.

Cheers,
Philipp

trait SimpleActor {

protected val mailbox = new MessageQueue

@volatile
protected var currentMessageHandler: PartialFunction[Any, Unit] =
messageHandler

protected var processing = false

protected def messageHandler: PartialFunction[Any, Unit]

protected def exceptionHandler: PartialFunction[Throwable, Unit] = Map()

protected def scheduler: IScheduler =
Scheduler

def !(msg: Any) = synchronized {
if (!processing &&
currentMessageHandler.isDefinedAt(msg)) {
processing = true
scheduler execute {
processMessage(msg)
processMailbox()
}
} else
mailbox.append(msg, null)
}

def processMessage(msg: Any) {
try {
val tmp = currentMessageHandler
currentMessageHandler = messageHandler
tmp(msg)
} catch {
case e: Exception =>
if (exceptionHandler.isDefinedAt(e))
exceptionHandler(e)
}
}

def processMailbox() {
var done = false
while (!done) {
val msg: Option[Any] = synchronized {
val qel = mailbox.extractFirst((m: Any) =>
currentMessageHandler.isDefinedAt(m))
if (qel eq null) {
processing = false
None
} else {
Some(qel.msg)
}
}
if (msg.isEmpty)
done = true
else
processMessage(msg.get)
}
}

def react(f: PartialFunction[Any, Unit]): Unit = synchronized {
currentMessageHandler = f
}

}

David Pollak wrote:
> Erik,
>
> Here's the Actor class that I build. It's a thing that has a mailbox
> and executes the stuff in its mailbox asynchronously from the act of
> putting stuff in its mailbox with the exception that if it's running in
> single threaded mode (for GAE), it does work-stealing.
>
> The only state is "is there a thread that's servicing the mailbox" and
> "the mailbox".
>
> I have a separate "Futures" class that allows for the concept of a "send
> and receive", but the future is included in the message.
>
> The whole idea is that everything is *very* lightweight and the level of
> complexity is very low.
>
> Thanks,
>
> David
>
> PS -- Please see the enclosed code
>
> On Fri, May 22, 2009 at 11:24 AM, Erik Engbrecht
> > wrote:
>
> Snipped from ESME mailing list:
>
> More broadly, there's a discussion going on on scala-internals
> about what
> can be done about Actors for Scala 2.8. There are a lot of people
> addressing the issue. I have a high degree of confidence that
> they will get
> to a reasonable solution for Scala's Actor library. However,
> Scala's Actors
> seem to be very heavy weight for what most apps I build
> (including ESME)
> need. I've been noodling with the idea of writing a very light
> weight Actor
> library so that Lift has more control over this escential part of
> interactive apps.
>
>
> David,
> Could you elaborate a bit on what your design goals/requirements
> would be if you were to build your own actors library for lift? I
> think it would be a good datapoint for those of us thinking about
> solutions to the various issues that the library has.
>
> -Erik

odersky
Joined: 2008-07-29,
User offline. Last seen 45 weeks 6 days ago.
Re: Re: design goals of actors library

Thanks for the careful assessment, Philip! I think there's value in
using Scala actors for Lift. The problem with concurrent frameworks
like actors is that something that looks deceptively simple at first
becomes rather tricky after a while, when features are added and
hidden bugs manifest themselves (which for concurrent applications can
be really late into a project cycle). So if feasible I would advocate
keeping one framework instead of two. That holds for implementation
and also documentation. There are going to be several books out this
year which describe Scala actors. You want to leverage that, so that
people don't have to learn multiple frameworks.

Just my two cents

loverdos
Joined: 2008-11-18,
User offline. Last seen 2 years 27 weeks ago.
Re: Re: design goals of actors library
If I may add my comment as a book author, the point about the books is substantial. I have planned a chapter about actors which (luckily (?) as it turns out...) has not reached a critical mass yet and I am now at the position to choose between these alternatives:
1) Keep going with Scala actors library, but as we all may understand I may not be able to follow all the changing implementation details from now on (as far as these changes affect the end user)
2) Go with describing the Lift needs from Actors and as a consequence follow David's elaboration
3) Go with both 1), 2) (middle-man consideration)
4) Abandon the thing altogether since things are not settled.
At this point I can only watch, but at the very near future a decision has to be made.

Just my thoughts.Christos

On Mon, May 25, 2009 at 20:33, martin odersky <martin.odersky@epfl.ch> wrote:
Thanks for the careful assessment, Philip! I think there's value in
using Scala actors for Lift. The problem with concurrent frameworks
like actors is that something that looks deceptively simple at first
becomes rather tricky after a while, when features are added and
hidden bugs manifest themselves (which for concurrent applications can
be really late into a project cycle). So if feasible I would advocate
keeping one framework instead of two. That holds for implementation
and also documentation. There are going to be several books out this
year which describe Scala actors. You want to leverage that, so that
people don't have to learn multiple frameworks.

Just my two cents

David Pollak
Joined: 2008-12-16,
User offline. Last seen 42 years 45 weeks ago.
Re: Re: design goals of actors library
Please do #1.  No matter what happens with Lift's Actor decision, Scala's Actors are the standard and that should not change.


On Tue, May 26, 2009 at 2:09 AM, Christos KK Loverdos <loverdos@gmail.com> wrote:
If I may add my comment as a book author, the point about the books is substantial. I have planned a chapter about actors which (luckily (?) as it turns out...) has not reached a critical mass yet and I am now at the position to choose between these alternatives:
1) Keep going with Scala actors library, but as we all may understand I may not be able to follow all the changing implementation details from now on (as far as these changes affect the end user)
2) Go with describing the Lift needs from Actors and as a consequence follow David's elaboration
3) Go with both 1), 2) (middle-man consideration)
4) Abandon the thing altogether since things are not settled.
At this point I can only watch, but at the very near future a decision has to be made.

Just my thoughts.Christos

On Mon, May 25, 2009 at 20:33, martin odersky <martin.odersky@epfl.ch> wrote:
Thanks for the careful assessment, Philip! I think there's value in
using Scala actors for Lift. The problem with concurrent frameworks
like actors is that something that looks deceptively simple at first
becomes rather tricky after a while, when features are added and
hidden bugs manifest themselves (which for concurrent applications can
be really late into a project cycle). So if feasible I would advocate
keeping one framework instead of two. That holds for implementation
and also documentation. There are going to be several books out this
year which describe Scala actors. You want to leverage that, so that
people don't have to learn multiple frameworks.

Just my two cents

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