sbt/launch/Locks.scala

51 lines
1.2 KiB
Scala
Raw Normal View History

package xsbt.boot
import java.io.{File, FileOutputStream}
import java.nio.channels.FileChannel
import java.util.concurrent.Callable
// gets a file lock by first getting a JVM-wide lock.
object Locks extends xsbti.GlobalLock
{
2009-10-18 04:40:02 +02:00
private[this] val locks = new Cache[File, GlobalLock](new GlobalLock(_))
def apply[T](file: File, action: Callable[T]) =
2009-10-18 04:40:02 +02:00
synchronized { locks(file.getCanonicalFile).withLock(action) }
private[this] class GlobalLock(file: File)
{
private[this] var fileLocked = false
def withLock[T](run: Callable[T]): T =
synchronized
{
if(fileLocked)
run.call
else
{
fileLocked = true
try { withFileLock(run) }
finally { fileLocked = false }
}
}
private[this] def withFileLock[T](run: Callable[T]): T =
{
def withChannel(channel: FileChannel) =
{
val freeLock = channel.tryLock
if(freeLock eq null)
{
2009-10-18 04:40:02 +02:00
System.out.println("Waiting for lock on " + file + " to be available...");
val lock = channel.lock
try { run.call }
finally { lock.release() }
}
else
{
try { run.call }
finally { freeLock.release() }
}
}
Using(new FileOutputStream(file).getChannel)(withChannel)
}
}
}