summaryrefslogtreecommitdiff
path: root/src/actors/scala/actors/ActorTask.scala
blob: 21d7a0a1ad14d6455e50555b510e5ca7bd6af311 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
/*                     __                                               *\
**     ________ ___   / /  ___     Scala API                            **
**    / __/ __// _ | / /  / _ |    (c) 2005-2013, LAMP/EPFL             **
**  __\ \/ /__/ __ |/ /__/ __ |                                         **
** /____/\___/_/ |_/____/_/ | |                                         **
**                          |/                                          **
\*                                                                      */



package scala.actors

/**
 *  @author Philipp Haller
 *  @note   This class inherits a public var called 'msg' from ReactorTask,
 *  and also defines a constructor parameter which shadows it (which makes any
 *  changes to the underlying var invisible.) I can't figure out what's supposed
 *  to happen, so I renamed the constructor parameter to at least be less confusing.
 */
private[actors] class ActorTask(actor: InternalActor,
                                fun: () => Unit,
                                handler: PartialFunction[Any, Any],
                                initialMsg: Any)
  extends ReplyReactorTask(actor, fun, handler, initialMsg) {

  protected override def beginExecution() {
    super.beginExecution()
    actor.synchronized { // shouldExit guarded by actor
      if (actor.shouldExit)
        actor.exit()
    }
  }

  protected override def terminateExecution(e: Throwable) {
    val senderInfo = try { Some(actor.internalSender) } catch {
      case _: Exception => None
    }
    // !!! If this is supposed to be setting the current contents of the
    // inherited mutable var rather than always the value given in the constructor,
    // then it should be changed from initialMsg to msg.
    val uncaught = UncaughtException(actor,
                                     if (initialMsg != null) Some(initialMsg) else None,
                                     senderInfo,
                                     Thread.currentThread,
                                     e)

    val todo = actor.synchronized {
      val res = if (!actor.links.isEmpty)
        actor.exitLinked(uncaught)
      else {
        super.terminateExecution(e)
        () => {}
      }
      res
    }

    todo()
  }

}