summaryrefslogtreecommitdiff
path: root/src/actors/scala/actors/Actor.scala
diff options
context:
space:
mode:
authorPhilipp Haller <hallerp@gmail.com>2006-10-03 12:50:09 +0000
committerPhilipp Haller <hallerp@gmail.com>2006-10-03 12:50:09 +0000
commit6ce056f31e1fea835b33203dd864f1ee4edf587c (patch)
tree4b452ed52572e54b3f830917e4f24874fc1721e1 /src/actors/scala/actors/Actor.scala
parent8d3d085f4bc64bfe019e49675e64073e5a73f60a (diff)
downloadscala-6ce056f31e1fea835b33203dd864f1ee4edf587c.tar.gz
scala-6ce056f31e1fea835b33203dd864f1ee4edf587c.tar.bz2
scala-6ce056f31e1fea835b33203dd864f1ee4edf587c.zip
Added scaladoc comments to most of the public t...
Added scaladoc comments to most of the public types and methods.
Diffstat (limited to 'src/actors/scala/actors/Actor.scala')
-rw-r--r--src/actors/scala/actors/Actor.scala272
1 files changed, 260 insertions, 12 deletions
diff --git a/src/actors/scala/actors/Actor.scala b/src/actors/scala/actors/Actor.scala
index f6dc77d672..157f2631b8 100644
--- a/src/actors/scala/actors/Actor.scala
+++ b/src/actors/scala/actors/Actor.scala
@@ -2,10 +2,23 @@ package scala.actors
import scala.collection.mutable.HashSet
+/**
+ This object provides functions for the definition of actors and
+ reactors, as well as all actor operations, such as
+ <code>receive</code>, <code>react</code>, <code>reply</code>,
+ etc.
+
+ @author Philipp Haller
+ */
object Actor {
private[actors] val selfs = new java.util.WeakHashMap(16, 0.5f)
+ /**
+ Returns the currently executing actor. Should be used instead
+ of <code>this</code> in all blocks of code executed by
+ actors.
+ */
def self: Actor = synchronized {
val t = Thread.currentThread()
if (t.isInstanceOf[ActorThread])
@@ -20,6 +33,10 @@ object Actor {
}
}
+ /**
+ Creates an instance of a thread-based actor executing <code>body</code>,
+ and starts it.
+ */
def actor(body: => Unit): ActorThread = synchronized {
val actor = new ActorThread {
def act() = body
@@ -28,6 +45,11 @@ object Actor {
actor
}
+ /**
+ Creates an instance of a thread-based actor specifying a
+ channel which can be used for typed communication with other
+ actors.
+ */
def actor[a](ch: Channel[a])(body: => Unit): ActorThread = synchronized {
val actor = new ActorThread {
def act() = body
@@ -37,6 +59,10 @@ object Actor {
actor
}
+ /**
+ Creates an instance of an event-based reactor executing
+ <code>body</code>, and starts it.
+ */
def reactor(body: => Unit): Reactor = synchronized {
val reactor = new Reactor {
def act() = body
@@ -45,18 +71,53 @@ object Actor {
reactor
}
+ /**
+ Receives a message from the mailbox of
+ <code>self</code>. Blocks if no message matching any of the
+ cases of <code>f</code> can be received.
+
+ Only (thread-based) actors may call this method. It fails at
+ runtime if executed by a reactor.
+ */
def receive[a](f: PartialFunction[Any, a]): a =
self.in.receive(f)
+ /**
+ Receives a message from the mailbox of
+ <code>self</code>. Blocks at most <code>msec</code>
+ milliseconds if no message matching any of the cases of
+ <code>f</code> can be received. If no message could be
+ received the <code>TIMEOUT</code> action is executed if
+ specified.
+
+ Only (thread-based) actors may call this method. It fails at
+ runtime if executed by a reactor.
+ */
def receiveWithin[R](msec: long)(f: PartialFunction[Any, R]): R =
self.in.receiveWithin(msec)(f)
+ /**
+ <code>receive</code> for event-based reactors.
+
+ Actions in <code>f</code> have to contain the rest of the
+ computation of <code>self</code>, as this method will never
+ return.
+ */
def react(f: PartialFunction[Any, Unit]): Nothing =
self.in.react(f)
+ /**
+ <code>receiveWithin</code> for event-based reactors.
+
+ Actions in <code>f</code> have to contain the rest of the
+ computation of <code>self</code>, as this method will never
+ return.
+ */
+
def reactWithin(msec: long)(f: PartialFunction[Any, Unit]): Nothing =
self.in.reactWithin(msec)(f)
+ /*
def eventloop(f: PartialFunction[Any, Unit]): Nothing =
self.in.react(new RecursiveProxyHandler(self, f))
@@ -69,7 +130,12 @@ object Actor {
self.in.react(this)
}
}
+ */
+ /**
+ Used for receiving a message from a specific actor.
+ Example: <code>from (a) receive { //... }</code>
+ */
def from(r: Actor): FromReceive =
new FromReceive(r)
@@ -78,14 +144,23 @@ object Actor {
self.in.receiveFrom(r)(f)
}
+ /**
+ Returns the actor which sent the last received message.
+ */
def sender: Actor = self.sender
+ /**
+ Send <code>msg</code> to the actor waiting in a call to
+ <code>!?</code>.
+ */
def reply(msg: Any): Unit = sender.reply ! msg
+ /**
+ Send <code>()</code> to the actor waiting in a call to
+ <code>!?</code>.
+ */
def reply(): Unit = reply(())
- def forward(msg: Any): Unit = self.in.forward(msg)
-
private[actors] trait Body[T] {
def orElse(other: => T): T
def andThen(other: => T): T
@@ -96,7 +171,7 @@ object Actor {
def andThen(other: => Unit): Unit = seq(body, other)
}
- def choose(alt1: => Unit, alt2: => Unit): Unit = {
+ private[actors] def choose(alt1: => Unit, alt2: => Unit): Unit = {
val s = self
// save former custom suspendActor function
// (e.g. from further orElse)
@@ -117,24 +192,63 @@ object Actor {
}
}
- def loop(b: => Unit): Unit = {
+ /**
+ Causes <code>self</code> to repeatedly execute
+ <code>body</code>.
+ */
+ def loop(body: => Unit): Unit = {
val s = self
- s.kill = () => { b; s.kill() }
- b
+ s.kill = () => { body; s.kill() }
+ body
}
- def seq(b1: => Unit, b2: => Unit): Unit = {
+ /**
+ Causes <code>self</code> to execute <code>first</code>
+ followed by <code>next</code>.
+ */
+ def seq(first: => Unit, next: => Unit): Unit = {
val s = self
- s.kill = () => { b2 }
- b1
+ s.kill = () => { next }
+ first
}
+ /**
+ Links <code>self</code> to actor <code>to</code>.
+ */
def link(to: Actor): Actor = self.link(to)
+
+ /**
+ Links <code>self</code> to actor defined by <code>body</code>.
+ */
def link(body: => Unit): Actor = self.link(body)
+
+ /**
+ Unlinks <code>self</code> from actor <code>from</code>.
+ */
def unlink(from: Actor): Unit = self.unlink(from)
+
+ /**
+ Terminates execution of <code>self</code> with the following
+ effect on linked actors:
+
+ For each linked actor <code>a</code> with
+ <code>trapExit</code> set to <code>true</code>, send message
+ <code>Exit(self, reason)</code> to <code>a</code>.
+
+ For each linked actor <code>a</code> with
+ <code>trapExit</code> set to <code>false</code> (default),
+ call <code>a.exit(reason)</code> if
+ <code>!reason.equals("normal")</code>.
+ */
def exit(reason: String): Unit = self.exit(reason)
}
+/**
+ This trait defines commonalities between thread-based and
+ event-based actors.
+
+ @author Philipp Haller
+ */
trait Actor {
private[actors] val in = new Channel[Any]
@@ -154,12 +268,23 @@ trait Actor {
rc.receiver = this
}
- /*
- Specification of behavior
+ /**
+ The behavior of an actor is specified by implementing this
+ abstract method. Note that the preferred way to create actors
+ is through the <code>actor</code> and <code>reactor</code>
+ methods defined in object <code>Actor</code>.
*/
def act(): Unit
+ /**
+ Sends <code>msg</code> to this actor (asynchronous).
+ */
def !(msg: Any): Unit = in ! msg
+
+ /**
+ Sends <code>msg</code> to this actor and awaits reply
+ (synchronous).
+ */
def !?(msg: Any): Any = in !? msg
private[actors] def sender: Actor
@@ -180,12 +305,18 @@ trait Actor {
private val links = new HashSet[Actor]
+ /**
+ Links <code>self</code> to actor <code>to</code>.
+ */
def link(to: Actor): Actor = {
links += to
to.linkTo(this)
to
}
+ /**
+ Links <code>self</code> to actor defined by <code>body</code>.
+ */
def link(body: => Unit): Actor = {
val actor = new ActorThread {
def act() = body
@@ -198,6 +329,9 @@ trait Actor {
private[actors] def linkTo(to: Actor): Unit =
links += to
+ /**
+ Unlinks <code>self</code> from actor <code>from</code>.
+ */
def unlink(from: Actor): Unit = {
links -= from
from.unlinkFrom(this)
@@ -210,6 +344,19 @@ trait Actor {
private[actors] var exitReason: String = ""
+ /**
+ Terminates execution of <code>self</code> with the following
+ effect on linked actors:
+
+ For each linked actor <code>a</code> with
+ <code>trapExit</code> set to <code>true</code>, send message
+ <code>Exit(self, reason)</code> to <code>a</code>.
+
+ For each linked actor <code>a</code> with
+ <code>trapExit</code> set to <code>false</code> (default),
+ call <code>a.exit(reason)</code> if
+ <code>!reason.equals("normal")</code>.
+ */
def exit(reason: String): Unit
private[actors] def exit(from: Actor, reason: String): Unit = {
@@ -249,9 +396,27 @@ trait Actor {
}
}
+/**
+ Messages of this type are sent to each actor <code>a</code>
+ that is linked to an actor <code>b</code> whenever
+ <code>b</code> terminates and <code>a</code> has
+ <code>trapExit</code> set to <code>true</code>.
+
+ @author Philipp Haller
+ */
case class Exit(from: Actor, reason: String)
+/**
+ This class provides an implementation for actors based on
+ threads. To be able to create instances of this class, the
+ inherited abstract method <code>act()</code> has to be
+ implemented. Note that the preferred way of creating
+ thread-based actors is through the <code>actor</code> method
+ defined in object <code>Actor</code>.
+
+ @author Philipp Haller
+ */
abstract class ActorThread extends Thread with ThreadedActor {
override def run(): Unit = {
try {
@@ -271,14 +436,46 @@ abstract class ActorThread extends Thread with ThreadedActor {
}
}
+ /**
+ Terminates execution of <code>self</code> with the following
+ effect on linked actors:
+
+ For each linked actor <code>a</code> with
+ <code>trapExit</code> set to <code>true</code>, send message
+ <code>Exit(self, reason)</code> to <code>a</code>.
+
+ For each linked actor <code>a</code> with
+ <code>trapExit</code> set to <code>false</code> (default),
+ call <code>a.exit(reason)</code> if
+ <code>!reason.equals("normal")</code>.
+ */
def exit(reason: String): Unit = {
exitReason = reason
interrupt()
}
}
-class ActorProxy(t: Thread) extends ThreadedActor {
+/**
+ This class provides a dynamic actor proxy for normal Java
+ threads.
+
+ @author Philipp Haller
+ */
+private[actors] class ActorProxy(t: Thread) extends ThreadedActor {
def act(): Unit = {}
+ /**
+ Terminates execution of <code>self</code> with the following
+ effect on linked actors:
+
+ For each linked actor <code>a</code> with
+ <code>trapExit</code> set to <code>true</code>, send message
+ <code>Exit(self, reason)</code> to <code>a</code>.
+
+ For each linked actor <code>a</code> with
+ <code>trapExit</code> set to <code>false</code> (default),
+ call <code>a.exit(reason)</code> if
+ <code>!reason.equals("normal")</code>.
+ */
def exit(reason: String): Unit = {
exitReason = reason
t.interrupt()
@@ -286,18 +483,53 @@ class ActorProxy(t: Thread) extends ThreadedActor {
}
+/**
+ This object provides methods for creating, registering, and
+ selecting remotely accessible actors.
+
+ A remote actor is typically created like this:
+ <pre>
+ actor {
+ alive(9010)
+ register('myName, self)
+
+ // behavior
+ }
+ </pre>
+
+ It can be accessed by an actor running on a (possibly)
+ different node by selecting it in the following way:
+ <pre>
+ actor {
+ // ...
+ val c = select(TcpNode("127.0.0.1", 9010), 'myName)
+ c ! msg
+ // ...
+ }
+ </pre>
+
+ @author Philipp Haller
+ */
object RemoteActor {
import remote.NetKernel
import remote.TcpService
private val kernels = new scala.collection.mutable.HashMap[Actor, NetKernel]
+ /**
+ Makes <code>self</code> remotely accessible on TCP port
+ <code>port</code>.
+ */
def alive(port: int): Unit = {
val serv = new TcpService(port)
serv.start()
kernels += Actor.self -> serv.kernel
}
+ /**
+ Registers <code>a</code> under <code>name</code> on this
+ node.
+ */
def register(name: Symbol, a: Actor): Unit = {
val kernel = kernels.get(Actor.self) match {
case None => {
@@ -311,6 +543,10 @@ object RemoteActor {
kernel.register(name, a)
}
+ /**
+ Returns (a proxy for) the actor registered under
+ <code>name</code> on <code>node</code>.
+ */
def select(node: Node, name: Symbol): Actor =
new Reactor {
def act(): Unit = {}
@@ -342,11 +578,23 @@ case class TcpNode(address: String, port: Int) extends Node
case class JxtaNode(group: String) extends Node
+/**
+ This class is used by our efficient message queue
+ implementation.
+ */
private[actors] abstract class MessageQueueResult[Msg] {
def msg: Msg
def sender: Actor
}
+/**
+ The class <code>MessageQueue</code> provides an efficient
+ implementation of a message queue specialized for this actor
+ library. Classes in this package are supposed to be the only
+ clients of this class.
+
+ @author Martin Odersky, Philipp Haller
+ */
private[actors] class MessageQueue[Msg] extends MessageQueueResult[Msg] {
var msg: Msg = _
var sender: Actor = _