change IdentityHashComparator to fall back to a real one

System.identityHashCode is not guaranteed to be consistent with equals()
(cannot be, just imagine more than 2^32 objects); fix it by checking
equals in case 0 would be returned and fall back to a real Comparator in
case that’s needed.
This commit is contained in:
Roland 2012-02-10 20:47:59 +01:00
parent 34d3c0ad15
commit 43913b0490
2 changed files with 19 additions and 5 deletions

View file

@ -9,7 +9,8 @@ import akka.actor.{ ActorCell, ActorRef }
import java.util.concurrent.{ LinkedBlockingQueue, ConcurrentLinkedQueue, ConcurrentSkipListSet }
import annotation.tailrec
import java.util.concurrent.atomic.AtomicBoolean
import akka.util.Duration
import akka.util.{ Duration, Helpers }
import java.util.Comparator
/**
* An executor based event driven dispatcher which will try to redistribute work from busy actors to idle actors. It is assumed
@ -35,10 +36,13 @@ class BalancingDispatcher(
_shutdownTimeout: Duration)
extends Dispatcher(_prerequisites, _id, throughput, throughputDeadlineTime, mailboxType, _executorServiceFactoryProvider, _shutdownTimeout) {
val buddies = new ConcurrentSkipListSet[ActorCell](akka.util.Helpers.IdentityHashComparator)
val buddies = new ConcurrentSkipListSet[ActorCell](
Helpers.identityHashComparator(new Comparator[ActorCell] {
def compare(l: ActorCell, r: ActorCell) = l.self.path compareTo r.self.path
}))
val messageQueue: MessageQueue = mailboxType match {
case u: UnboundedMailbox new QueueBasedMessageQueue with UnboundedMessageQueueSemantics {
case _: UnboundedMailbox new QueueBasedMessageQueue with UnboundedMessageQueueSemantics {
final val queue = new ConcurrentLinkedQueue[Envelope]
}
case BoundedMailbox(cap, timeout) new QueueBasedMessageQueue with BoundedMessageQueueSemantics {

View file

@ -21,8 +21,18 @@ object Helpers {
if (diff > 0) 1 else if (diff < 0) -1 else 0
}
val IdentityHashComparator = new Comparator[AnyRef] {
def compare(a: AnyRef, b: AnyRef): Int = compareIdentityHash(a, b)
/**
* Create a comparator which will efficiently use `System.identityHashCode`,
* unless that happens to be the same for two non-equals objects, in which
* case the supplied real comparator is used; the comparator must be
* consistent with equals, otherwise it would not be an enhancement over
* the identityHashCode.
*/
def identityHashComparator[T <: AnyRef](comp: Comparator[T]): Comparator[T] = new Comparator[T] {
def compare(a: T, b: T): Int = compareIdentityHash(a, b) match {
case 0 if a != b comp.compare(a, b)
case x x
}
}
final val base64chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+~"