summaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
authorLi Haoyi <haoyi.sg@gmail.com>2017-12-13 23:28:15 -0800
committerLi Haoyi <haoyi.sg@gmail.com>2017-12-13 23:28:15 -0800
commita97697a3c7294eb6dda30740fc6cdd92a9966ccd (patch)
treec34dc6c2587c69dd496682c003036b8b65028119 /core
parente83989f4e15fc80820794a0f4e2db806f117a1a9 (diff)
downloadmill-a97697a3c7294eb6dda30740fc6cdd92a9966ccd.tar.gz
mill-a97697a3c7294eb6dda30740fc6cdd92a9966ccd.tar.bz2
mill-a97697a3c7294eb6dda30740fc6cdd92a9966ccd.zip
First pass at implementing long-lived `Worker` objects. These currently are managed by the `Evaluator`, which is now a stateful object that shouldn't be thrown away every time.
We still need to update the code/test-suite to make the `Evaluator` hang around in between `evaluate` calls
Diffstat (limited to 'core')
-rw-r--r--core/src/main/scala/mill/define/Worker.scala35
-rw-r--r--core/src/main/scala/mill/eval/Evaluator.scala12
-rw-r--r--core/src/main/scala/mill/util/Ctx.scala11
3 files changed, 53 insertions, 5 deletions
diff --git a/core/src/main/scala/mill/define/Worker.scala b/core/src/main/scala/mill/define/Worker.scala
new file mode 100644
index 00000000..385d795f
--- /dev/null
+++ b/core/src/main/scala/mill/define/Worker.scala
@@ -0,0 +1,35 @@
+package mill.define
+
+import mill.util.Ctx
+
+import scala.annotation.compileTimeOnly
+
+/**
+ * Worker serves three purposes:
+ *
+ * - Cache in-memory state between tasks (e.g. object initialization)
+ * - Including warm classloaders with isolated bytecode
+ * - Mutex to limit concurrency
+ * - Manage out-of-process subprocesses <-- skip this for now
+ *
+ * Key usage:
+ *
+ * - T{
+ * ZincWorker().compile(a() + b())
+ * }
+ *
+ * Desugars into:
+ *
+ * - T.zipMap(ZincWorker, a, b){ (z, a1, b1) => z.compile(a1, b1) }
+ *
+ * Workers are shoehorned into the `Task` type. This lets them fit nicely in
+ * the `T{...}` syntax, as well as being statically-inspectable before
+ * evaluating the task graph. The Worker defines how it is evaluated, but it's
+ * evaluation/caching/lifecycle are controlled by the `Evaluator`
+ */
+trait Worker[V] extends Task[V]{
+ val inputs = Nil
+ def make(): V
+ def evaluate(args: Ctx) = args.workerFor(this)
+ def path = this.getClass.getCanonicalName.filter(_ != '$').split('.')
+} \ No newline at end of file
diff --git a/core/src/main/scala/mill/eval/Evaluator.scala b/core/src/main/scala/mill/eval/Evaluator.scala
index 9995215a..dffd609e 100644
--- a/core/src/main/scala/mill/eval/Evaluator.scala
+++ b/core/src/main/scala/mill/eval/Evaluator.scala
@@ -4,11 +4,12 @@ import java.net.URLClassLoader
import ammonite.ops._
import ammonite.runtime.SpecialClassLoader
-import mill.define.{Graph, Target, Task}
+import mill.define.{Graph, Target, Task, Worker}
import mill.discover.Mirror
import mill.discover.Mirror.LabelledTarget
import mill.discover.Mirror.Segment.{Cross, Label}
import mill.util
+import mill.util.Ctx.WorkerCtx
import mill.util._
import scala.collection.mutable
@@ -18,7 +19,7 @@ class Evaluator(workspacePath: Path,
log: Logger,
sel: List[Mirror.Segment] = List(),
classLoaderSig: Seq[(Path, Long)] = Evaluator.classLoaderSig){
-
+ val workerCache = mutable.Map.empty[Worker[_], _]
def evaluate(goals: OSet[Task[_]]): Evaluator.Results = {
mkdir(workspacePath)
@@ -163,7 +164,12 @@ class Evaluator(workspacePath: Path,
val args = new Ctx(
targetInputValues.toArray[Any],
targetDestPath.orNull,
- multiLogger
+ multiLogger,
+ new WorkerCtx{
+ def workerFor[T](x: mill.define.Worker[T]): T = {
+ workerCache.getOrElseUpdate(x, x.make()).asInstanceOf[T]
+ }
+ }
)
val out = System.out
diff --git a/core/src/main/scala/mill/util/Ctx.scala b/core/src/main/scala/mill/util/Ctx.scala
index 7a0a5694..3b8fb171 100644
--- a/core/src/main/scala/mill/util/Ctx.scala
+++ b/core/src/main/scala/mill/util/Ctx.scala
@@ -4,7 +4,8 @@ import java.io.PrintStream
import ammonite.ops.Path
import mill.define.Applicative.ImplicitStub
-import mill.util.Ctx.{ArgCtx, DestCtx, LogCtx}
+import mill.define.Worker
+import mill.util.Ctx.{ArgCtx, DestCtx, LogCtx, WorkerCtx}
import scala.annotation.compileTimeOnly
@@ -22,10 +23,16 @@ object Ctx{
trait ArgCtx{
def args: IndexedSeq[_]
}
+ trait WorkerCtx{
+ def workerFor[T](x: mill.define.Worker[T]): T
+ }
}
class Ctx(val args: IndexedSeq[_],
val dest: Path,
- val log: Logger) extends DestCtx with LogCtx with ArgCtx{
+ val log: Logger,
+ workerCtx0: Ctx.WorkerCtx) extends DestCtx with LogCtx with ArgCtx with WorkerCtx{
+
+ def workerFor[T](x: mill.define.Worker[T]): T = workerCtx0.workerFor(x)
def length = args.length
def apply[T](index: Int): T = {
if (index >= 0 && index < args.length) args(index).asInstanceOf[T]