Refactored mailbox configuration
This commit is contained in:
parent
e90d5b1b69
commit
9ea09c3e36
15 changed files with 416 additions and 329 deletions
|
|
@ -5,13 +5,15 @@
|
|||
package se.scalablesolutions.akka.dispatch
|
||||
|
||||
import se.scalablesolutions.akka.actor.{Actor, ActorRef, ActorInitializationException}
|
||||
import se.scalablesolutions.akka.util.{SimpleLock, Duration, HashCode, Logging}
|
||||
import se.scalablesolutions.akka.util.ReflectiveAccess.EnterpriseModule
|
||||
import se.scalablesolutions.akka.AkkaException
|
||||
|
||||
import org.multiverse.commitbarriers.CountDownCommitBarrier
|
||||
import se.scalablesolutions.akka.AkkaException
|
||||
|
||||
import java.util.{Queue, List}
|
||||
import java.util.concurrent._
|
||||
import concurrent.forkjoin.LinkedTransferQueue
|
||||
import se.scalablesolutions.akka.util.{SimpleLock, Duration, HashCode, Logging}
|
||||
|
||||
/**
|
||||
* @author <a href="http://jonasboner.com">Jonas Bonér</a>
|
||||
|
|
@ -21,30 +23,30 @@ final class MessageInvocation(val receiver: ActorRef,
|
|||
val sender: Option[ActorRef],
|
||||
val senderFuture: Option[CompletableFuture[Any]],
|
||||
val transactionSet: Option[CountDownCommitBarrier]) {
|
||||
if (receiver eq null) throw new IllegalArgumentException("receiver is null")
|
||||
if (receiver eq null) throw new IllegalArgumentException("Receiver can't be null")
|
||||
|
||||
def invoke = try {
|
||||
receiver.invoke(this)
|
||||
} catch {
|
||||
case e: NullPointerException => throw new ActorInitializationException(
|
||||
"Don't call 'self ! message' in the Actor's constructor (e.g. body of the class).")
|
||||
"Don't call 'self ! message' in the Actor's constructor (in Scala this means in the body of the class).")
|
||||
}
|
||||
|
||||
override def hashCode(): Int = synchronized {
|
||||
override def hashCode(): Int = {
|
||||
var result = HashCode.SEED
|
||||
result = HashCode.hash(result, receiver.actor)
|
||||
result = HashCode.hash(result, message.asInstanceOf[AnyRef])
|
||||
result
|
||||
}
|
||||
|
||||
override def equals(that: Any): Boolean = synchronized {
|
||||
override def equals(that: Any): Boolean = {
|
||||
that != null &&
|
||||
that.isInstanceOf[MessageInvocation] &&
|
||||
that.asInstanceOf[MessageInvocation].receiver.actor == receiver.actor &&
|
||||
that.asInstanceOf[MessageInvocation].message == message
|
||||
}
|
||||
|
||||
override def toString = synchronized {
|
||||
override def toString = {
|
||||
"MessageInvocation[" +
|
||||
"\n\tmessage = " + message +
|
||||
"\n\treceiver = " + receiver +
|
||||
|
|
@ -55,83 +57,24 @@ final class MessageInvocation(val receiver: ActorRef,
|
|||
}
|
||||
}
|
||||
|
||||
class MessageQueueAppendFailedException(message: String) extends AkkaException(message)
|
||||
|
||||
/**
|
||||
* @author <a href="http://jonasboner.com">Jonas Bonér</a>
|
||||
*/
|
||||
trait MessageQueue {
|
||||
val dispatcherLock = new SimpleLock
|
||||
def enqueue(handle: MessageInvocation)
|
||||
def dequeue(): MessageInvocation
|
||||
def size: Int
|
||||
def isEmpty: Boolean
|
||||
}
|
||||
|
||||
/* Tells the dispatcher that it should create a bounded mailbox with the specified push timeout
|
||||
* (If capacity > 0)
|
||||
*/
|
||||
case class MailboxConfig(capacity: Int, pushTimeOut: Option[Duration], blockingDequeue: Boolean) {
|
||||
|
||||
/**
|
||||
* Creates a MessageQueue (Mailbox) with the specified properties
|
||||
* bounds = whether the mailbox should be bounded (< 0 means unbounded)
|
||||
* pushTime = only used if bounded, indicates if and how long an enqueue should block
|
||||
* blockDequeue = whether dequeues should block or not
|
||||
*
|
||||
* The bounds + pushTime generates a MessageQueueAppendFailedException if enqueue times out
|
||||
*/
|
||||
def newMailbox(bounds: Int = capacity,
|
||||
pushTime: Option[Duration] = pushTimeOut,
|
||||
blockDequeue: Boolean = blockingDequeue) : MessageQueue =
|
||||
if (capacity > 0) new DefaultBoundedMessageQueue(bounds,pushTime,blockDequeue)
|
||||
else new DefaultUnboundedMessageQueue(blockDequeue)
|
||||
}
|
||||
|
||||
class DefaultUnboundedMessageQueue(blockDequeue: Boolean) extends LinkedBlockingQueue[MessageInvocation] with MessageQueue {
|
||||
final def enqueue(handle: MessageInvocation) {
|
||||
this add handle
|
||||
}
|
||||
|
||||
final def dequeue(): MessageInvocation =
|
||||
if (blockDequeue) this.take()
|
||||
else this.poll()
|
||||
}
|
||||
|
||||
class DefaultBoundedMessageQueue(capacity: Int, pushTimeOut: Option[Duration], blockDequeue: Boolean) extends LinkedBlockingQueue[MessageInvocation](capacity) with MessageQueue {
|
||||
final def enqueue(handle: MessageInvocation) {
|
||||
if (pushTimeOut.isDefined) {
|
||||
if(!this.offer(handle,pushTimeOut.get.length,pushTimeOut.get.unit))
|
||||
throw new MessageQueueAppendFailedException("Couldn't enqueue message " + handle + " to " + toString)
|
||||
}
|
||||
else {
|
||||
this put handle
|
||||
}
|
||||
}
|
||||
|
||||
final def dequeue(): MessageInvocation =
|
||||
if (blockDequeue) this.take()
|
||||
else this.poll()
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @author <a href="http://jonasboner.com">Jonas Bonér</a>
|
||||
*/
|
||||
trait MessageDispatcher extends Logging {
|
||||
trait MessageDispatcher extends MailboxFactory with Logging {
|
||||
|
||||
protected val uuids = new ConcurrentSkipListSet[String]
|
||||
|
||||
def dispatch(invocation: MessageInvocation): Unit
|
||||
|
||||
def dispatch(invocation: MessageInvocation)
|
||||
def start: Unit
|
||||
|
||||
def start
|
||||
|
||||
def shutdown
|
||||
def shutdown: Unit
|
||||
|
||||
def register(actorRef: ActorRef) {
|
||||
if(actorRef.mailbox eq null)
|
||||
actorRef.mailbox = createMailbox(actorRef)
|
||||
if (actorRef.mailbox eq null) actorRef.mailbox = createMailbox(actorRef)
|
||||
uuids add actorRef.uuid
|
||||
}
|
||||
|
||||
def unregister(actorRef: ActorRef) = {
|
||||
uuids remove actorRef.uuid
|
||||
actorRef.mailbox = null
|
||||
|
|
@ -145,10 +88,5 @@ trait MessageDispatcher extends Logging {
|
|||
/**
|
||||
* Returns the size of the mailbox for the specified actor
|
||||
*/
|
||||
def mailboxSize(actorRef: ActorRef):Int
|
||||
|
||||
/**
|
||||
* Creates and returns a mailbox for the given actor
|
||||
*/
|
||||
protected def createMailbox(actorRef: ActorRef): AnyRef = null
|
||||
def mailboxSize(actorRef: ActorRef): Int
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue