diff options
author | Philipp Haller <hallerp@gmail.com> | 2006-10-03 12:50:09 +0000 |
---|---|---|
committer | Philipp Haller <hallerp@gmail.com> | 2006-10-03 12:50:09 +0000 |
commit | 6ce056f31e1fea835b33203dd864f1ee4edf587c (patch) | |
tree | 4b452ed52572e54b3f830917e4f24874fc1721e1 /src/actors/scala/actors/Actor.scala | |
parent | 8d3d085f4bc64bfe019e49675e64073e5a73f60a (diff) | |
download | scala-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.scala | 272 |
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 = _ |