2009-07-06 23:45:15 +02:00
|
|
|
/**
|
2009-12-27 16:01:53 +01:00
|
|
|
* Copyright (C) 2009-2010 Scalable Solutions AB <http://scalablesolutions.se>
|
2009-07-06 23:45:15 +02:00
|
|
|
*/
|
|
|
|
|
|
2009-10-08 19:01:04 +02:00
|
|
|
package se.scalablesolutions.akka.dispatch
|
2009-07-06 23:45:15 +02:00
|
|
|
|
|
|
|
|
import java.util.concurrent.LinkedBlockingQueue
|
|
|
|
|
import java.util.Queue
|
2009-08-11 12:16:50 +02:00
|
|
|
|
2010-06-01 09:23:45 +02:00
|
|
|
import se.scalablesolutions.akka.actor.{Actor, ActorRef}
|
2009-07-06 23:45:15 +02:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Dedicates a unique thread for each actor passed in as reference. Served through its messageQueue.
|
2010-05-21 20:08:49 +02:00
|
|
|
*
|
2009-07-06 23:45:15 +02:00
|
|
|
* @author <a href="http://jonasboner.com">Jonas Bonér</a>
|
|
|
|
|
*/
|
2010-06-01 09:23:45 +02:00
|
|
|
class ThreadBasedDispatcher(private val actor: ActorRef) extends MessageDispatcher {
|
2010-05-16 10:59:06 +02:00
|
|
|
private val name = actor.getClass.getName + ":" + actor.uuid
|
2010-07-18 07:13:43 +02:00
|
|
|
private val threadName = "akka:thread-based:dispatcher:" + name
|
2009-08-11 12:16:50 +02:00
|
|
|
private val queue = new BlockingMessageQueue(name)
|
2009-07-06 23:45:15 +02:00
|
|
|
private var selectorThread: Thread = _
|
|
|
|
|
@volatile private var active: Boolean = false
|
|
|
|
|
|
2010-05-21 20:08:49 +02:00
|
|
|
def dispatch(invocation: MessageInvocation) = queue.append(invocation)
|
2009-12-11 06:44:59 +01:00
|
|
|
|
2009-07-06 23:45:15 +02:00
|
|
|
def start = if (!active) {
|
2010-07-18 07:13:43 +02:00
|
|
|
log.debug("Starting up %s", toString)
|
2009-07-06 23:45:15 +02:00
|
|
|
active = true
|
2010-05-16 10:59:06 +02:00
|
|
|
selectorThread = new Thread(threadName) {
|
2009-07-06 23:45:15 +02:00
|
|
|
override def run = {
|
|
|
|
|
while (active) {
|
|
|
|
|
try {
|
2010-06-01 09:23:45 +02:00
|
|
|
actor.invoke(queue.take)
|
2009-07-06 23:45:15 +02:00
|
|
|
} catch { case e: InterruptedException => active = false }
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
selectorThread.start
|
|
|
|
|
}
|
2010-05-21 20:08:49 +02:00
|
|
|
|
2010-01-02 08:40:09 +01:00
|
|
|
def isShutdown = !active
|
|
|
|
|
|
2009-07-06 23:45:15 +02:00
|
|
|
def shutdown = if (active) {
|
2010-07-18 07:13:43 +02:00
|
|
|
log.debug("Shutting down %s", toString)
|
2009-07-06 23:45:15 +02:00
|
|
|
active = false
|
|
|
|
|
selectorThread.interrupt
|
2010-01-02 08:40:09 +01:00
|
|
|
references.clear
|
2009-07-06 23:45:15 +02:00
|
|
|
}
|
2010-07-18 07:13:43 +02:00
|
|
|
|
|
|
|
|
override def toString = "ThreadBasedDispatcher[" + threadName + "]"
|
2009-07-06 23:45:15 +02:00
|
|
|
}
|
|
|
|
|
|
2009-08-11 12:16:50 +02:00
|
|
|
class BlockingMessageQueue(name: String) extends MessageQueue {
|
2009-12-11 16:37:44 +01:00
|
|
|
// FIXME: configure the LinkedBlockingQueue in BlockingMessageQueue, use a Builder like in the ReactorBasedThreadPoolEventDrivenDispatcher
|
2009-07-06 23:45:15 +02:00
|
|
|
private val queue = new LinkedBlockingQueue[MessageInvocation]
|
2009-12-11 06:44:59 +01:00
|
|
|
def append(invocation: MessageInvocation) = queue.put(invocation)
|
2009-07-06 23:45:15 +02:00
|
|
|
def take: MessageInvocation = queue.take
|
|
|
|
|
def read(destination: Queue[MessageInvocation]) = throw new UnsupportedOperationException
|
|
|
|
|
def interrupt = throw new UnsupportedOperationException
|
2009-08-11 12:16:50 +02:00
|
|
|
}
|