Skip to content

Instantly share code, notes, and snippets.

@MishaelRosenthal
Last active November 24, 2015 12:16
Show Gist options
  • Select an option

  • Save MishaelRosenthal/df8fcf94d4b97a732598 to your computer and use it in GitHub Desktop.

Select an option

Save MishaelRosenthal/df8fcf94d4b97a732598 to your computer and use it in GitHub Desktop.
Provides a lock per key, and enables sync execution per key.
package core
import org.slf4j.LoggerFactory
import scala.collection.mutable
class LockPool{
type Lock = AnyRef
case class LockAndCounter(lock: AnyRef, counter: Int)
val logger = LoggerFactory.getLogger(getClass)
val pool = mutable.Map[String, LockAndCounter]()
def syncByKey[T](key: String)(f: => T): T = {
val lock = retrieveLock(key)
val res = try {
lock.synchronized {
logger.debug(s"Locked $key")
val inner = f
logger.debug(s"Finished f $key")
inner
}
} finally {
logger.debug(s"Released $key")
decreaseCounter(key)
}
res
}
def retrieveLock(key: String): Lock = synchronized{
pool.get(key) match {
case Some(lockAndKey) =>
val newLockAndKey = lockAndKey.copy(counter = lockAndKey.counter + 1)
pool.update(key, newLockAndKey)
newLockAndKey.lock
case _ =>
val lockAndCounter = LockAndCounter(new AnyRef{}, 1)
pool += key -> lockAndCounter
lockAndCounter.lock
}
}
private def decreaseCounter(key: String) = synchronized{
pool.get(key) match {
case Some(lockAndKey) =>
if(lockAndKey.counter == 1)
pool -= key
else
pool.update(key, lockAndKey.copy(counter = lockAndKey.counter - 1))
case _ =>
throw new MatchError(s"Key does not exist in pool: $key")
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment