/* sbt -- Simple Build Tool
 * Copyright 2009  Mark Harrah
 */
package sbt

import scala.actors.Actor
import scala.collection.mutable.{ArrayBuffer, Buffer, HashMap, HashSet, ListBuffer, Map, PriorityQueue, Set}

object object sbt.ParallelRunnerParallelRunner
{
	def [D <: sbt.Dag[D]](D,(D) => String,(D) => Option[String],Int,(D) => sbt.Logger)List[sbt.WorkFailure[D]]run[>: Nothing <: sbt.Dag[D]D <: Dag[D]](Dnode: DD, (D) => Stringname: D => String, (D) => Option[String]action: D => Option[String], IntmaximumTasks: IntInt, (D) => sbt.Loggerlog: D => Logger): List[sbt.WorkFailure[D]]List[WorkFailure[D]] =
	{
		val sbt.BasicDagScheduler[D]jobScheduler = sbt.BasicDagScheduler[D]new sbt.BasicDagScheduler[D]BasicDagScheduler(Dnode, (D) => Stringname, (Dd: DD) => Int(1)1)
		val sbt.Distributor[sbt.Work[D]]distributor = sbt.Distributor[sbt.Work[D]]new sbt.Distributor[sbt.Work[D]]Distributor(sbt.BasicDagScheduler[D]jobScheduler, ((D) => Option[String])(sbt.Work[D])Option[String]withWork((D) => Option[String]action), IntmaximumTasks, ((D) => sbt.Logger)(sbt.Work[D])sbt.LoggerwithWork((D) => sbt.Loggerlog))
		sbt.Distributor[sbt.Work[D]]distributor.()scala.actors.Actorstart()
		val List[sbt.WorkFailure[sbt.Work[D]]]result = (sbt.Distributor[sbt.Work[D]]distributor (Any)Any!? object sbt.StartStart).List[sbt.WorkFailure[sbt.Work[D]]]asInstanceOf[List[sbt.WorkFailure[sbt.Work[D]]]List[WorkFailure[Work[D]]]]
		for( ((sbt.WorkFailure[sbt.Work[D]]) => sbt.WorkFailure[D])List[sbt.WorkFailure[D]]WorkFailure(sbt.Work[D]work, Stringmessage) <- List[sbt.WorkFailure[sbt.Work[D]]]result ) yield (D,String)sbt.WorkFailure[D]WorkFailure(sbt.Work[D]work.=> Ddata, java.lang.String("Error running ")"Error running " (Any)java.lang.String+ (D)Stringname(sbt.Work[D]work.=> Ddata) (Any)java.lang.String+ java.lang.String(": ")": " (Any)java.lang.String+ Stringmessage)
	}
	private def [D, T]((D) => T)(sbt.Work[D])TwithWork[>: Nothing <: AnyD, >: Nothing <: AnyT]((D) => Tf: D => T)(sbt.Work[D]w: sbt.Work[D]Work[D]) = (D)Tf(sbt.Work[D]w.=> Ddata)
}
private case object object sbt.StartStart
final class class Distributor[D] extends java.lang.Object with scala.actors.Actor with NotNull with ScalaObjectDistributor[>: Nothing <: AnyD](sbt.Scheduler[D]scheduler: sbt.Scheduler[D]Scheduler[D], (D) => Option[String]doWork: D => Option[String], Intworkers: IntInt, (D) => sbt.Loggerlog: D => Logger) extends scala.actors.ActorActor with NotNullNotNull
{
	private val scala.collection.mutable.HashSet[Distributor.this.Worker]running = scala.collection.mutable.HashSet[Distributor.this.Worker]new scala.collection.mutable.HashSet[Distributor.this.Worker]HashSet[Worker]
	private val scala.collection.mutable.Buffer[Distributor.this.Worker]idle: scala.collection.mutable.Buffer[Distributor.this.Worker]Buffer[Worker] = scala.collection.mutable.ArrayBuffer[Distributor.this.Worker]new scala.collection.mutable.ArrayBuffer[Distributor.this.Worker]ArrayBuffer[Worker]
	=> scala.collection.mutable.Buffer[Distributor.this.Worker]idle (Iterable[Distributor.this.Worker])Unit++= object ArrayArray.((Int) => Distributor.this.Worker)(Int)Array[Distributor.this.Worker]fromFunction( (Inti: IntInt) => { val Distributor.this.Workerw = Distributor.this.Workernew Distributor.this.WorkerWorker; Distributor.this.Workerw.()scala.actors.Actorstart(); Distributor.this.Workerw } )(Intworkers)
	
	def ()Unitact
	{
		(PartialFunction[Any,Unit])Unitreceive Unit{
			Unitcase object sbt.StartStart =>
				(Any)Unitreply {
					()UnitrunNext()
					sbt.Scheduler[D]scheduler.=> Iterable[sbt.WorkFailure[D]]result
				}
		}
		()Nothingexit()
	}
	private def ()UnitrunNext()
	{
		val Booleandone = ()Booleannext()
		Unitif(=> Boolean!Booleandone)
		{
			(PartialFunction[Any,Unit])Unitreceive
			Unit{
				Unitcase Done(Option[String]result, Distributor.this.Workerworker, Ddata) =>
					=> scala.collection.mutable.HashSet[Distributor.this.Worker]running (Distributor.this.Worker)Unit-= Distributor.this.Workerworker
					=> scala.collection.mutable.Buffer[Distributor.this.Worker]idle (Distributor.this.Worker)Unit+= Distributor.this.Workerworker
					sbt.Scheduler[D]scheduler.(D,Option[String])Unitcomplete(Ddata, Option[String]result)
					()UnitrunNext()
			}
		}
	}
	private def ()Booleannext() =
	{
		Booleanif(=> scala.collection.mutable.Buffer[Distributor.this.Worker]idle.=> BooleanisEmpty)
			Boolean(false)false
		else Booleanif(sbt.Scheduler[D]scheduler.=> BooleanhasPending)
		{
			val Intavailable = => scala.collection.mutable.Buffer[Distributor.this.Worker]idle.=> Intsize
			val Seq[D]next = sbt.Scheduler[D]scheduler.(Int)Seq[D]next(Intavailable)
			val IntnextSize = Seq[D]next.=> Intsize
			Unitif(IntnextSize (Int)Boolean<= Int(0)0)
				(Boolean)Unitassume(=> Boolean!=> scala.collection.mutable.HashSet[Distributor.this.Worker]running.=> BooleanisEmpty)
			else
			{
				(Boolean)Unitassume(IntnextSize (Int)Boolean> Int(0)0)
				(Boolean)Unitassume(IntnextSize (Int)Boolean<= Intavailable)
				for(((D) => Unit)Unitdata <- Seq[D]next)
				{
					val Distributor.this.Workerworker = => scala.collection.mutable.Buffer[Distributor.this.Worker]idle.(Int)Distributor.this.Workerremove(=> scala.collection.mutable.Buffer[Distributor.this.Worker]idle.=> Intsize (Int)Int- Int(1)1)
					=> scala.collection.mutable.HashSet[Distributor.this.Worker]running (Distributor.this.Worker)Unit+= Distributor.this.Workerworker
					Distributor.this.Workerworker (Any)Unit! (D)Distributor.this.RunRun(Ddata)
				}
			}
			Boolean(false)false
		}
		else Booleanif(=> scala.collection.mutable.HashSet[Distributor.this.Worker]running.=> BooleanisEmpty)
		{
			=> scala.collection.mutable.Buffer[Distributor.this.Worker]idle.((Distributor.this.Worker) => Unit)Unitforeach(Distributor.this.Worker_ (Any)Unit! object Distributor.this.ShutdownShutdown)
			Boolean(true)true
		}
		else
			Boolean(false)false
	}
	private class class Worker extends java.lang.Object with scala.actors.Actor with NotNull with ScalaObjectWorker extends scala.actors.ActorActor with NotNullNotNull
	{
		def ()Unitact
		{
			Unitwhile(Boolean(true)true)
			{
				(PartialFunction[Any,Unit])Unitreceive
				Unit{
					Unitcase Run(Ddata)  =>
					{
						val Option[String]result = object sbt.ControlControl.(=> String,sbt.Logger)(=> Option[String])Option[String]trapUnit(java.lang.String("")"", (D)sbt.Loggerlog(Ddata))((D)Option[String]doWork(Ddata))
						Distributor.this.typeDistributor.this (Any)Unit! (Option[String],Distributor.this.Worker,D)Distributor.this.DoneDone(Option[String]result, Distributor.this.Workerthis, Ddata)
					}
					Nothingcase object Distributor.this.ShutdownShutdown => ()Nothingexit()
				}
			}
		}
	}
	
	private case object object Distributor.this.ShutdownShutdown extends NotNullNotNull
	private case class class Run extends java.lang.Object with NotNull with ScalaObject with ProductRun(Ddata: DD) extends NotNullNotNull
	private case class class Done extends java.lang.Object with NotNull with ScalaObject with ProductDone(Option[String]result: Option[String]Option[String], Distributor.this.Workerworker: Distributor.this.WorkerWorker, Ddata: DD) extends NotNullNotNull
}
final case class class WorkFailure[D] extends java.lang.Object with NotNull with ScalaObject with ProductWorkFailure[>: Nothing <: AnyD](Dwork: DD, Stringmessage: StringString) extends NotNullNotNull
{
	override def ()StringtoString = => Stringmessage
}
trait trait Scheduler[D] extends java.lang.Object with NotNullScheduler[>: Nothing <: AnyD] extends NotNullNotNull
{
	def (D,Option[String])Unitcomplete(Dd: DD, Option[String]result: Option[String]Option[String]): UnitUnit
	def => BooleanhasPending: BooleanBoolean
	def (Int)Seq[D]next(Intmax: IntInt): Seq[D]Seq[D]
	def => Iterable[sbt.WorkFailure[D]]result: Iterable[sbt.WorkFailure[D]]Iterable[WorkFailure[D]]
}

private sealed abstract class class Work[D] extends java.lang.Object with Ordered[sbt.Work[D]] with ScalaObjectWork[>: Nothing <: AnyD](val Stringname: StringString, val Ddata: DD, val Intcost: IntInt) extends Ordered[sbt.Work[D]]Ordered[Work[D]]
{
	def (sbt.Work[D])Intcompare(sbt.Work[D]o: sbt.Work[D]Work[D]) = implicit scala.Predef.intWrapper : (Int)scala.runtime.RichIntpathCost (Int)Intcompare sbt.Work[D]o.=> IntpathCost
	def => IntpathCost: IntInt
	override def ()java.lang.StringtoString = => Stringname (Any)java.lang.String+ java.lang.String("(")"(" (Any)java.lang.String+ => IntpathCost (Any)java.lang.String+ java.lang.String(")")")"
}

private[sbt] abstract class class AbstractDagScheduler[D <: sbt.Dag[D], W] extends java.lang.Object with sbt.Scheduler[W] with ScalaObjectAbstractDagScheduler[>: Nothing <: sbt.Dag[D]D <: Dag[D], >: Nothing <: AnyW](Droot: DD, (D) => Stringname: D => String) extends sbt.Scheduler[W]Scheduler[W]
{
	protected val scala.collection.mutable.Map[W,scala.collection.mutable.Set[W]]remainingDeps: scala.collection.mutable.Map[W,scala.collection.mutable.Set[W]]Map[W, Set[W]] = scala.collection.mutable.HashMap[W,scala.collection.mutable.Set[W]]new scala.collection.mutable.HashMap[W,scala.collection.mutable.Set[W]]HashMap
	protected val scala.collection.mutable.Map[W,scala.collection.mutable.Set[W]]reverseDeps: scala.collection.mutable.Map[W,scala.collection.mutable.Set[W]]Map[W, Set[W]] = scala.collection.mutable.HashMap[W,scala.collection.mutable.Set[W]]new scala.collection.mutable.HashMap[W,scala.collection.mutable.Set[W]]HashMap
	protected val scala.collection.mutable.ListBuffer[sbt.WorkFailure[W]]errors = scala.collection.mutable.ListBuffer[sbt.WorkFailure[W]]new scala.collection.mutable.ListBuffer[sbt.WorkFailure[W]]ListBuffer[WorkFailure[W]]
	
	()Unitsetup()
	
	def => List[sbt.WorkFailure[W]]result = => scala.collection.mutable.ListBuffer[sbt.WorkFailure[W]]errors.=> List[sbt.WorkFailure[W]]readOnly
	def (W,Option[String])Unitcomplete(Wwork: WW, Option[String]result: Option[String]Option[String])
	{
		Option[String]result Unitmatch
		{
			Unitcase object NoneNone => (W)UnitworkComplete(Wwork)
			Unitcase Some(StringerrorMessage) =>
			{
				def (W)Unitclear(Ww: WW)
				{
					=> scala.collection.mutable.Map[W,scala.collection.mutable.Set[W]]remainingDeps (W)Unit-= Ww
					for(((scala.collection.mutable.Set[W]) => Unit)Unitdeps <- => scala.collection.mutable.Map[W,scala.collection.mutable.Set[W]]reverseDeps.(W)Option[scala.collection.mutable.Set[W]]removeKey(Ww); ((W) => Unit)Unitdep <- scala.collection.mutable.Set[W]deps)
						(W)Unitclear(Wdep)
				}
				(W)Unitclear(Wwork)
				=> scala.collection.mutable.ListBuffer[sbt.WorkFailure[W]]errors (sbt.WorkFailure[W])Unit+= (W,String)sbt.WorkFailure[W]WorkFailure(Wwork, StringerrorMessage)
			}
		}
	}
	private def (W)UnitworkComplete(Wwork: WW)
	{
		for(((scala.collection.mutable.Set[W]) => Unit)Unitdeps <- => scala.collection.mutable.Map[W,scala.collection.mutable.Set[W]]reverseDeps.(W)Option[scala.collection.mutable.Set[W]]removeKey(Wwork); ((W) => Unit)Unitdep <- scala.collection.mutable.Set[W]deps; ((scala.collection.mutable.Set[W]) => Unit)UnitdepRemaining <- => scala.collection.mutable.Map[W,scala.collection.mutable.Set[W]]remainingDeps.(W)Option[scala.collection.mutable.Set[W]]get(Wdep))
		{
			scala.collection.mutable.Set[W]depRemaining (W)Unit-= Wwork
			Unitif(scala.collection.mutable.Set[W]depRemaining.=> BooleanisEmpty)
			{
				=> scala.collection.mutable.Map[W,scala.collection.mutable.Set[W]]remainingDeps (W)Unit-= Wdep
				(W)UnitworkReady(Wdep)
			}
		}
	}
	protected def (W)UnitworkReady(Wwork: WW): UnitUnit
	def => BooleanhasReady: BooleanBoolean
	def => BooleanhasPending = => BooleanhasReady (Boolean)Boolean|| => Boolean!=> scala.collection.mutable.Map[W,scala.collection.mutable.Set[W]]remainingDeps.=> BooleanisEmpty
	protected def (String,D)WworkConstructor(Stringname: StringString, Ddata: DD): WW
	
	protected def ()Unitsetup()
	{
		(D)Unitsetup(Droot)
		val Iterable[W]startReady = for( (((W, scala.collection.mutable.Set[W])) => W)Iterable[W](Wkey, scala.collection.mutable.Set[W]value) <- => scala.collection.mutable.Map[W,scala.collection.mutable.Set[W]]remainingDeps if(scala.collection.mutable.Set[W]value.=> BooleanisEmpty)) yield Wkey
		=> scala.collection.mutable.Map[W,scala.collection.mutable.Set[W]]remainingDeps (Iterable[W])Unit--= Iterable[W]startReady
		Iterable[W]startReady.((W) => Unit)Unitforeach((W)UnitworkReady)
	}
	private def (D)Unitsetup(Dnode: DD)
	{
		val scala.collection.mutable.HashMap[D,W]dToWork = scala.collection.mutable.HashMap[D,W]new scala.collection.mutable.HashMap[D,W]HashMap[D, W]()
		def (D)WgetWork(Dnode: DD) = scala.collection.mutable.HashMap[D,W]dToWork.(D,=> W)WgetOrElseUpdate(Dnode, (D)WcreateWork(Dnode))
		def (D)WcreateWork(Dnode: DD): WW =
		{
			val Iterable[W]workDependencies = Dnode.=> Iterable[D]dependencies.((D) => W)Iterable[W]map((D)WgetWork(D_))
			val Ww = (String,D)WworkConstructor((D)Stringname(Dnode), Dnode)
			=> scala.collection.mutable.Map[W,scala.collection.mutable.Set[W]]remainingDeps(Ww) = (W*)scala.collection.mutable.Set[W]HashSet(Iterable[W]workDependencies.=> Seq[W]toSeq: _*)
			for(((W) => Unit)Unitdep <- Iterable[W]workDependencies)
				=> scala.collection.mutable.Map[W,scala.collection.mutable.Set[W]]reverseDeps.(W,=> scala.collection.mutable.Set[W])scala.collection.mutable.Set[W]getOrElseUpdate(Wdep, scala.collection.mutable.HashSet[W]new scala.collection.mutable.HashSet[W]HashSet[W]) (W)Unit+= Ww
			Ww
		}
		(D)WgetWork(Dnode)
	}
}
private class class BasicDagScheduler[D <: sbt.Dag[D]] extends sbt.AbstractDagScheduler[D,sbt.Work[D]] with ScalaObjectBasicDagScheduler[>: Nothing <: sbt.Dag[D]D <: Dag[D]](Droot: DD, (D) => Stringname: D => String, (D) => Intcost: D => Int) extends
{
	private val scala.collection.mutable.PriorityQueue[sbt.Work[D]]ready = scala.collection.mutable.PriorityQueue[sbt.Work[D]]new scala.collection.mutable.PriorityQueue[sbt.Work[D]]PriorityQueue[Work[D]]

} with sbt.AbstractDagScheduler[D,sbt.Work[D]]AbstractDagScheduler[D, Work[D]](Droot, (D) => Stringname) {
	
	def (Int)List[sbt.Work[D]]next(Intmax: IntInt): List[sbt.Work[D]]List[Work[D]] =
	{
		(Boolean)Unitrequire(Intmax (Int)Boolean> Int(0)0)
		def (Int)List[sbt.Work[D]]nextImpl(Intremaining: IntInt): List[sbt.Work[D]]List[Work[D]] =
			List[sbt.Work[D]]if(Intremaining (Int)Boolean<= Int(0)0 (Boolean)Boolean|| => scala.collection.mutable.PriorityQueue[sbt.Work[D]]ready.=> BooleanisEmpty)
				object NilNil
			else
				=> scala.collection.mutable.PriorityQueue[sbt.Work[D]]ready.()sbt.Work[D]dequeue (sbt.Work[D])List[sbt.Work[D]]:: (Int)List[sbt.Work[D]]nextImpl(Intremaining (Int)Int- Int(1)1)
		(Int)List[sbt.Work[D]]nextImpl(Intmax)
	}
	
	protected def (sbt.Work[D])UnitworkReady(sbt.Work[D]dep: sbt.Work[D]Work[D]) { => scala.collection.mutable.PriorityQueue[sbt.Work[D]]ready (sbt.Work[D])Unit+= sbt.Work[D]dep }
	def => BooleanhasReady = => Boolean!=> scala.collection.mutable.PriorityQueue[sbt.Work[D]]ready.=> BooleanisEmpty
	protected def (String,D)sbt.Work[D]workConstructor(Stringname: StringString, Ddata: DD) =
		template $anon extends sbt.Work[D]new sbt.Work[D]Work(Stringname, Ddata, (D)Intcost(Ddata)) {
			lazy val IntpathCost = => scala.collection.mutable.Map[sbt.Work[D],scala.collection.mutable.Set[sbt.Work[D]]]reverseDeps.(sbt.Work[D],=> Collection[sbt.Work[D]] with (sbt.Work[D] with Int) => Boolean)Collection[sbt.Work[D]] with (sbt.Work[D] with Int) => BooleangetOrElse(sbt.Work[D]{ ... }this, object NilNil).(Int)((Int, sbt.Work[D]) => Int)IntfoldLeft(Int(0)0)(implicit scala.Predef.intWrapper : (Int)scala.runtime.RichInt_ (Int)Intmax sbt.Work[D]_.=> IntpathCost) (Int)Int+ this.typethis.=> Intcost
		}
	protected override def ()Unitsetup()
	{
		super.()Unitsetup()
		=> scala.collection.mutable.Map[sbt.Work[D],scala.collection.mutable.Set[sbt.Work[D]]]remainingDeps.=> Iterator[sbt.Work[D]]keys.((sbt.Work[D]) => Unit)Unitforeach(sbt.Work[D]dep => sbt.Work[D]dep.=> IntpathCost)
	}
}