2009-06-05 22:08:53 +02:00
|
|
|
/**
|
|
|
|
|
* Copyright (C) 2009 Scalable Solutions.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
package se.scalablesolutions.akka.kernel.reactor
|
|
|
|
|
|
2009-07-28 10:45:41 +02:00
|
|
|
import java.util.{LinkedList, Queue, List}
|
2009-07-03 17:15:36 +02:00
|
|
|
import java.util.concurrent.TimeUnit
|
2009-07-01 15:29:06 +02:00
|
|
|
import java.util.HashMap
|
2009-06-05 22:08:53 +02:00
|
|
|
|
|
|
|
|
trait MessageDispatcherBase extends MessageDispatcher {
|
2009-07-03 17:15:36 +02:00
|
|
|
val CONCURRENT_MODE = kernel.Kernel.config.getBool("akka.actor.concurrent-mode", false)
|
|
|
|
|
val MILLISECONDS = TimeUnit.MILLISECONDS
|
|
|
|
|
|
2009-07-06 23:45:15 +02:00
|
|
|
val queue = new ReactiveMessageQueue
|
2009-06-05 22:08:53 +02:00
|
|
|
|
2009-06-25 13:07:58 +02:00
|
|
|
@volatile protected var active: Boolean = false
|
2009-07-06 23:45:15 +02:00
|
|
|
protected val messageHandlers = new HashMap[AnyRef, MessageInvoker]
|
2009-06-05 22:08:53 +02:00
|
|
|
protected var selectorThread: Thread = _
|
|
|
|
|
protected val guard = new Object
|
|
|
|
|
|
2009-07-06 23:45:15 +02:00
|
|
|
def messageQueue = queue
|
|
|
|
|
|
2009-07-28 15:21:25 +02:00
|
|
|
def registerHandler(key: AnyRef, handler: MessageInvoker) = guard.synchronized {
|
2009-06-05 22:08:53 +02:00
|
|
|
messageHandlers.put(key, handler)
|
|
|
|
|
}
|
|
|
|
|
|
2009-07-28 15:21:25 +02:00
|
|
|
def unregisterHandler(key: AnyRef) = guard.synchronized {
|
2009-06-05 22:08:53 +02:00
|
|
|
messageHandlers.remove(key)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
def shutdown = if (active) {
|
|
|
|
|
active = false
|
|
|
|
|
selectorThread.interrupt
|
|
|
|
|
doShutdown
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Subclass callback. Override if additional shutdown behavior is needed.
|
|
|
|
|
*/
|
|
|
|
|
protected def doShutdown = {}
|
|
|
|
|
}
|
2009-07-06 23:45:15 +02:00
|
|
|
|
|
|
|
|
class ReactiveMessageQueue extends MessageQueue {
|
|
|
|
|
private[kernel] val queue: Queue[MessageInvocation] = new LinkedList[MessageInvocation]
|
|
|
|
|
@volatile private var interrupted = false
|
|
|
|
|
|
|
|
|
|
def append(handle: MessageInvocation) = queue.synchronized {
|
|
|
|
|
queue.offer(handle)
|
|
|
|
|
queue.notifyAll
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
def prepend(handle: MessageInvocation) = queue.synchronized {
|
|
|
|
|
queue.add(handle)
|
|
|
|
|
queue.notifyAll
|
|
|
|
|
}
|
|
|
|
|
|
2009-07-28 10:45:41 +02:00
|
|
|
def read(destination: List[MessageInvocation]) = queue.synchronized {
|
2009-07-06 23:45:15 +02:00
|
|
|
while (queue.isEmpty && !interrupted) queue.wait
|
2009-07-28 10:45:41 +02:00
|
|
|
if (!interrupted) while (!queue.isEmpty) destination.add(queue.remove)
|
2009-07-06 23:45:15 +02:00
|
|
|
else interrupted = false
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
def interrupt = queue.synchronized {
|
|
|
|
|
interrupted = true
|
|
|
|
|
queue.notifyAll
|
|
|
|
|
}
|
|
|
|
|
}
|