Making sure that dispatcher scheduling for shutdown is checked even if unregister throws up
This commit is contained in:
parent
39b374ba22
commit
1613ff5111
2 changed files with 24 additions and 6 deletions
|
|
@ -0,0 +1,19 @@
|
||||||
|
/**
|
||||||
|
* Copyright (C) 2009-2011 Typesafe Inc. <http://www.typesafe.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
package akka.dispatch;
|
||||||
|
|
||||||
|
import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
|
||||||
|
import java.util.concurrent.atomic.AtomicLongFieldUpdater;
|
||||||
|
import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
|
||||||
|
|
||||||
|
abstract class AbstractMessageDispatcher {
|
||||||
|
private volatile int _shutdownSchedule; // not initialized because this is faster: 0 == UNSCHEDULED
|
||||||
|
protected final static AtomicIntegerFieldUpdater<AbstractMessageDispatcher> shutdownScheduleUpdater =
|
||||||
|
AtomicIntegerFieldUpdater.newUpdater(AbstractMessageDispatcher.class, "_shutdownSchedule");
|
||||||
|
|
||||||
|
private volatile long _inhabitants; // not initialized because this is faster
|
||||||
|
protected final static AtomicLongFieldUpdater<AbstractMessageDispatcher> inhabitantsUpdater =
|
||||||
|
AtomicLongFieldUpdater.newUpdater(AbstractMessageDispatcher.class, "_inhabitants");
|
||||||
|
}
|
||||||
|
|
@ -107,15 +107,14 @@ abstract class MessageDispatcher(val app: ActorSystem) extends AbstractMessageDi
|
||||||
/**
|
/**
|
||||||
* Attaches the specified actor instance to this dispatcher
|
* Attaches the specified actor instance to this dispatcher
|
||||||
*/
|
*/
|
||||||
final def attach(actor: ActorCell) {
|
final def attach(actor: ActorCell): Unit = register(actor)
|
||||||
register(actor)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Detaches the specified actor instance from this dispatcher
|
* Detaches the specified actor instance from this dispatcher
|
||||||
*/
|
*/
|
||||||
final def detach(actor: ActorCell) {
|
final def detach(actor: ActorCell): Unit = try {
|
||||||
unregister(actor)
|
unregister(actor)
|
||||||
|
} finally {
|
||||||
ifSensibleToDoSoThenScheduleShutdown()
|
ifSensibleToDoSoThenScheduleShutdown()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -152,7 +151,7 @@ abstract class MessageDispatcher(val app: ActorSystem) extends AbstractMessageDi
|
||||||
() ⇒ if (inhabitantsUpdater.decrementAndGet(this) == 0) ifSensibleToDoSoThenScheduleShutdown()
|
() ⇒ if (inhabitantsUpdater.decrementAndGet(this) == 0) ifSensibleToDoSoThenScheduleShutdown()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Don't call this, this calls you. See "attach" for only invocation
|
* If you override it, you must call it. But only ever once. See "attach" for only invocation
|
||||||
*/
|
*/
|
||||||
protected[akka] def register(actor: ActorCell) {
|
protected[akka] def register(actor: ActorCell) {
|
||||||
inhabitantsUpdater.incrementAndGet(this)
|
inhabitantsUpdater.incrementAndGet(this)
|
||||||
|
|
@ -161,7 +160,7 @@ abstract class MessageDispatcher(val app: ActorSystem) extends AbstractMessageDi
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Don't call this, this calls you. See "detach" for the only invocation
|
* If you override it, you must call it. But only ever once. See "detach" for the only invocation
|
||||||
*/
|
*/
|
||||||
protected[akka] def unregister(actor: ActorCell) {
|
protected[akka] def unregister(actor: ActorCell) {
|
||||||
inhabitantsUpdater.decrementAndGet(this)
|
inhabitantsUpdater.decrementAndGet(this)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue