summaryrefslogtreecommitdiff
path: root/src/actors/scala/actors/ActorGC.scala
diff options
context:
space:
mode:
authorPhilipp Haller <hallerp@gmail.com>2009-04-21 09:55:52 +0000
committerPhilipp Haller <hallerp@gmail.com>2009-04-21 09:55:52 +0000
commit2ffeb5af819f3bb3ad441ae80ba6270ae1b976c7 (patch)
tree7ad0400d93151e080a3fa6f957f78b27219e71ee /src/actors/scala/actors/ActorGC.scala
parent92f91f0e063e62c089916ebaed085e62fd4d64a2 (diff)
downloadscala-2ffeb5af819f3bb3ad441ae80ba6270ae1b976c7.tar.gz
scala-2ffeb5af819f3bb3ad441ae80ba6270ae1b976c7.tar.bz2
scala-2ffeb5af819f3bb3ad441ae80ba6270ae1b976c7.zip
Fixed bug in ActorGC. Added more comments.
Diffstat (limited to 'src/actors/scala/actors/ActorGC.scala')
-rw-r--r--src/actors/scala/actors/ActorGC.scala30
1 files changed, 30 insertions, 0 deletions
diff --git a/src/actors/scala/actors/ActorGC.scala b/src/actors/scala/actors/ActorGC.scala
index c1c31ba06c..2e36d4a14a 100644
--- a/src/actors/scala/actors/ActorGC.scala
+++ b/src/actors/scala/actors/ActorGC.scala
@@ -14,20 +14,40 @@ import java.lang.ref.{Reference, WeakReference, ReferenceQueue}
import scala.collection.mutable.{HashMap, HashSet}
+/**
+ * ActorGC keeps track of the number of live actors being managed by a
+ * a scheduler so that it can shutdown when all of the actors it manages have
+ * either been explicitly terminated or garbage collected.
+ *
+ * When an actor is started, it is registered with the ActorGC via the
+ * <code>newActor</code> method, and when an actor is knowingly terminated
+ * (e.g. act method finishes, exit explicitly called, an exception is thrown),
+ * the ActorGC is informed via the <code>terminated</code> method.
+ */
class ActorGC {
private var pendingReactions = 0
private val termHandlers = new HashMap[Actor, () => Unit]
+ /** Actors are added to refQ in newActor. */
private val refQ = new ReferenceQueue[Actor]
+
+ /**
+ * This is a set of references to all the actors registered with
+ * this ActorGC. It is maintained so that the WeakReferences will not be GC'd
+ * before the actors to which they point.
+ */
private val refSet = new HashSet[Reference[t] forSome { type t <: Actor }]
+ /** newActor is invoked whenever a new actor is started. */
def newActor(a: Actor) = synchronized {
+ // registers a reference to the actor with the ReferenceQueue
val wr = new WeakReference[Actor](a, refQ)
refSet += wr
pendingReactions += 1
}
+ /** Removes unreachable actors from refSet. */
def gc() = synchronized {
// check for unreachable actors
def drainRefQ() {
@@ -67,6 +87,16 @@ class ActorGC {
// do nothing
}
+ // find the weak reference that points to the terminated actor, if any
+ refSet.find((ref: Reference[t] forSome { type t <: Actor }) => ref.get() == a) match {
+ case Some(r) =>
+ // invoking clear will not cause r to be enqueued
+ r.clear()
+ refSet -= r
+ case None =>
+ // do nothing
+ }
+
pendingReactions -= 1
}