From 5c20c07199bc35a99098e2a4c43729930a3e631a Mon Sep 17 00:00:00 2001 From: Patrik Nordwall Date: Thu, 13 Sep 2012 20:44:17 +0200 Subject: [PATCH] Use tuple to update ConsistentHash and routees together, see #944 --- .../routing/ConsistentHashingRouter.scala | 22 ++++++++++--------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/akka-actor/src/main/scala/akka/routing/ConsistentHashingRouter.scala b/akka-actor/src/main/scala/akka/routing/ConsistentHashingRouter.scala index e177fc413a..1e78025350 100644 --- a/akka-actor/src/main/scala/akka/routing/ConsistentHashingRouter.scala +++ b/akka-actor/src/main/scala/akka/routing/ConsistentHashingRouter.scala @@ -164,23 +164,25 @@ trait ConsistentHashingLike { this: RouterConfig ⇒ if (virtualNodesFactor == 0) routeeProvider.context.system.settings.DefaultVirtualNodesFactor else virtualNodesFactor - var consistentHashRoutees = new AtomicReference[IndexedSeq[ActorRef]] - @volatile var consistentHash: ConsistentHash[ActorRef] = null + // tuple of routees and the ConsistentHash, updated together in updateConsistentHash + val consistentHashRef = new AtomicReference[(IndexedSeq[ActorRef], ConsistentHash[ActorRef])]((null, null)) updateConsistentHash() // update consistentHash when routees has changed // changes to routees are rare and when no changes this is a quick operation def updateConsistentHash(): ConsistentHash[ActorRef] = { val currentRoutees = routeeProvider.routees - if (currentRoutees ne consistentHashRoutees.get) { - val oldConsistentHashRoutees = consistentHashRoutees.get - val rehash = currentRoutees != oldConsistentHashRoutees - // when other instance, same content, no need to re-hash, but try to set currentRoutees + val oldConsistentHashTuple = consistentHashRef.get + val (oldConsistentHashRoutees, oldConsistentHash) = oldConsistentHashTuple + if (currentRoutees ne oldConsistentHashRoutees) { + // when other instance, same content, no need to re-hash, but try to set routees + val consistentHash = + if (currentRoutees == oldConsistentHashRoutees) oldConsistentHash + else ConsistentHash(currentRoutees, vnodes) // re-hash // ignore, don't update, in case of CAS failure - if (consistentHashRoutees.compareAndSet(oldConsistentHashRoutees, currentRoutees) && rehash) - consistentHash = ConsistentHash(currentRoutees, vnodes) - } - consistentHash + consistentHashRef.compareAndSet(oldConsistentHashTuple, (currentRoutees, consistentHash)) + consistentHash + } else oldConsistentHash } def target(hashData: Any): ActorRef = try {