Added lock downgrades and fixed unlocking ordering

This commit is contained in:
Viktor Klang 2011-01-01 23:18:51 +01:00
parent d5095be95d
commit 63a182afd7

View file

@ -74,22 +74,24 @@ trait NettyRemoteClientModule extends RemoteClientModule with NettyRemoteShared
val key = makeKey(address) val key = makeKey(address)
lock.readLock.lock lock.readLock.lock
remoteClients.get(key) match { try {
case Some(client) => try { client } finally { lock.readLock.unlock } remoteClients.get(key) match {
case None => case Some(client) => client
lock.readLock.unlock case None =>
lock.writeLock.lock //Lock upgrade, not supported natively lock.readLock.unlock
try { lock.writeLock.lock //Lock upgrade, not supported natively
remoteClients.get(key) match { //Recheck for addition, race between upgrades try {
case Some(client) => client //If already populated by other writer remoteClients.get(key) match { //Recheck for addition, race between upgrades
case None => //Populate map case Some(client) => client //If already populated by other writer
val client = new ActiveRemoteClient(this, address, loader, self.notifyListeners _) case None => //Populate map
client.connect() val client = new ActiveRemoteClient(this, address, loader, self.notifyListeners _)
remoteClients += key -> client client.connect()
client remoteClients += key -> client
} client
} finally { lock.writeLock.unlock } }
} } finally { lock.readLock.lock; lock.writeLock.unlock } //downgrade
}
} finally { lock.readLock.unlock }
} }
/** /**
@ -99,22 +101,24 @@ trait NettyRemoteClientModule extends RemoteClientModule with NettyRemoteShared
val address = channel.getRemoteAddress.asInstanceOf[InetSocketAddress] val address = channel.getRemoteAddress.asInstanceOf[InetSocketAddress]
val key = makeKey(address) val key = makeKey(address)
lock.readLock.lock lock.readLock.lock
remoteClients.get(key) match { try {
case Some(client) => try { false } finally { lock.readLock.unlock } remoteClients.get(key) match {
case None => case Some(client) => false
lock.readLock.unlock case None =>
lock.writeLock.lock //Lock upgrade, not supported natively lock.readLock.unlock
try { lock.writeLock.lock //Lock upgrade, not supported natively
remoteClients.get(key) match { try {
case Some(client) => false remoteClients.get(key) match {
case None => case Some(client) => false
val client = new PassiveRemoteClient(this, address, channel, self.notifyListeners _ ) case None =>
client.connect() val client = new PassiveRemoteClient(this, address, channel, self.notifyListeners _ )
remoteClients.put(key, client) client.connect()
true remoteClients.put(key, client)
} true
} finally { lock.writeLock.unlock } }
} } finally { lock.readLock.lock; lock.writeLock.unlock } //downgrade
}
} finally { lock.readLock.unlock }
} }
/** /**
@ -124,22 +128,24 @@ trait NettyRemoteClientModule extends RemoteClientModule with NettyRemoteShared
val address = channel.getRemoteAddress.asInstanceOf[InetSocketAddress] val address = channel.getRemoteAddress.asInstanceOf[InetSocketAddress]
val key = makeKey(address) val key = makeKey(address)
lock.readLock.lock lock.readLock.lock
remoteClients.get(key) match { try {
case Some(client: PassiveRemoteClient) => remoteClients.get(key) match {
lock.readLock.unlock case Some(client: PassiveRemoteClient) =>
lock.writeLock.lock //Lock upgrade, not supported natively lock.readLock.unlock
try { lock.writeLock.lock //Lock upgrade, not supported natively
remoteClients.get(key) match { try {
case Some(client: ActiveRemoteClient) => false remoteClients.get(key) match {
case None => false case Some(client: ActiveRemoteClient) => false
case Some(client: PassiveRemoteClient) => case None => false
remoteClients.remove(key) case Some(client: PassiveRemoteClient) =>
true remoteClients.remove(key)
} true
} finally { lock.writeLock.unlock } }
//Otherwise, unlock the readlock and return false } finally { lock.readLock.lock; lock.writeLock.unlock } //downgrade
case _ => try { false } finally { lock.readLock.unlock } //Otherwise, unlock the readlock and return false
} case _ => false
}
} finally { lock.readLock.unlock }
} }
private def makeKey(a: InetSocketAddress): String = a match { private def makeKey(a: InetSocketAddress): String = a match {