Skip to content
This repository
Fetching contributors…

Cannot retrieve contributors at this time

file 75 lines (71 sloc) 2.087 kb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75
/* sbt -- Simple Build Tool
* Copyright 2009, 2010 Mark Harrah
*/
package xsbt.boot

import java.io.{File, FileOutputStream}
import java.nio.channels.FileChannel
import java.util.concurrent.Callable
import scala.collection.immutable.List

object GetLocks
{
/** Searches for Locks in parent class loaders before returning Locks from this class loader.
* Normal class loading doesn't work because the launcher class loader hides xsbt classes.*/
def find: xsbti.GlobalLock =
Loaders(getClass.getClassLoader.getParent).flatMap(tryGet).headOption.getOrElse(Locks)
private[this] def tryGet(loader: ClassLoader): List[xsbti.GlobalLock] =
try { getLocks0(loader) :: Nil } catch { case e: ClassNotFoundException => Nil }
private[this] def getLocks0(loader: ClassLoader) =
Class.forName("xsbt.boot.Locks$", true, loader).getField("MODULE$").get(null).asInstanceOf[xsbti.GlobalLock]
}

// gets a file lock by first getting a JVM-wide lock.
object Locks extends xsbti.GlobalLock
{
private[this] val locks = new Cache[File, Unit, GlobalLock]( (f, _) => new GlobalLock(f))
def apply[T](file: File, action: Callable[T]): T =
{
val lock =
synchronized
{
file.getParentFile.mkdirs()
file.createNewFile()
locks(file.getCanonicalFile, ())
}
lock.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)
{
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)
}
}
}
Something went wrong with that request. Please try again.