More user-friendly project watching

This commit is contained in:
Šesták Vít
2016-02-19 12:47:00 +01:00
parent a64f7c540b
commit 12f43f4b32
9 changed files with 151 additions and 25 deletions

View File

@@ -0,0 +1,40 @@
package com.ysoft.concurrent
import java.util.concurrent.atomic.AtomicBoolean
import scala.concurrent.{ExecutionContext, Future}
trait FutureLock[T] {
def whenLocked(cannotLock: => Future[T])(implicit executionContext: ExecutionContext): Future[T]
}
object FutureLock {
def futureLock[T](lock: AtomicBoolean)(f: => Future[T]): FutureLock[T] = new FutureLock[T]() {
override def whenLocked(cannotLock: => Future[T])(implicit executionContext: ExecutionContext): Future[T] = {
if (lock.compareAndSet(/*expect = */ false, /*update = */ true)) {
try {
f.andThen { case _ =>
val wasLocked = lock.getAndSet(false)
if (!wasLocked) {
throw new RuntimeException("The lock was not being held when trying to unlock")
}
}
} catch {
case e: Throwable =>
// So, the Exception was raised before creation of the Future. As a result, the Future will not relase the lock.
// In other words, its our responsibility to release the lock:
val wasLocked = lock.getAndSet(false)
if (!wasLocked) {
throw new RuntimeException("The lock was not being held when throwing the following exception", e)
}
throw e
}
} else {
cannotLock
}
}
}
}