mirror of
https://github.com/ysoftdevs/odc-analyzer.git
synced 2026-03-21 08:39:42 +01:00
More user-friendly project watching
This commit is contained in:
40
app/com/ysoft/concurrent/FutureLock.scala
Normal file
40
app/com/ysoft/concurrent/FutureLock.scala
Normal 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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user