blob: 8948ac676d9c6d9953fc621077b61665a9c3402c [file] [log] [blame]
Shinichiro Hamajib69bf8a2015-06-10 14:52:06 +09001// Copyright 2015 Google Inc. All rights reserved
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
Fumitoshi Ukai744bb2b2015-06-25 00:10:52 +090015package kati
Shinichiro Hamaji74a66002015-04-27 16:42:30 +090016
17import (
Shinichiro Hamajidbc6c132015-04-28 18:26:36 +090018 "container/heap"
Shinichiro Hamaji74a66002015-04-27 16:42:30 +090019 "fmt"
Shinichiro Hamajicedc5c82015-05-13 17:03:20 +090020 "os"
Shinichiro Hamaji74a66002015-04-27 16:42:30 +090021 "os/exec"
22 "strings"
23 "syscall"
24 "time"
25)
26
Fumitoshi Ukaidfb518b2015-06-25 13:19:55 +090027type job struct {
Shinichiro Hamaji74a66002015-04-27 16:42:30 +090028 n *DepNode
29 ex *Executor
Fumitoshi Ukaidfb518b2015-06-25 13:19:55 +090030 parents []*job
Shinichiro Hamaji74a66002015-04-27 16:42:30 +090031 outputTs int64
32 numDeps int
33 depsTs int64
Shinichiro Hamaji69bb7e42015-04-27 17:54:42 +090034 id int
Shinichiro Hamajia6808422015-05-13 18:00:50 +090035
36 runners []runner
Shinichiro Hamaji74a66002015-04-27 16:42:30 +090037}
38
39type runner struct {
40 output string
41 cmd string
42 echo bool
Shinichiro Hamaji74a66002015-04-27 16:42:30 +090043 ignoreError bool
44 shell string
45}
46
Fumitoshi Ukaidfb518b2015-06-25 13:19:55 +090047type jobResult struct {
48 j *job
49 w *worker
Shinichiro Hamaji69bb7e42015-04-27 17:54:42 +090050}
51
Fumitoshi Ukaidfb518b2015-06-25 13:19:55 +090052type newDep struct {
53 j *job
54 neededBy *job
Shinichiro Hamaji69bb7e42015-04-27 17:54:42 +090055}
56
Fumitoshi Ukaidfb518b2015-06-25 13:19:55 +090057type worker struct {
58 wm *workerManager
59 jobChan chan *job
Shinichiro Hamaji69bb7e42015-04-27 17:54:42 +090060 waitChan chan bool
61 doneChan chan bool
62}
63
Fumitoshi Ukaidfb518b2015-06-25 13:19:55 +090064type jobQueue []*job
Shinichiro Hamajidbc6c132015-04-28 18:26:36 +090065
Fumitoshi Ukaidfb518b2015-06-25 13:19:55 +090066func (jq jobQueue) Len() int { return len(jq) }
67func (jq jobQueue) Swap(i, j int) { jq[i], jq[j] = jq[j], jq[i] }
Shinichiro Hamajidbc6c132015-04-28 18:26:36 +090068
Fumitoshi Ukaidfb518b2015-06-25 13:19:55 +090069func (jq jobQueue) Less(i, j int) bool {
Shinichiro Hamajidbc6c132015-04-28 18:26:36 +090070 // First come, first serve, for GNU make compatibility.
71 return jq[i].id < jq[j].id
72}
73
Fumitoshi Ukaidfb518b2015-06-25 13:19:55 +090074func (jq *jobQueue) Push(x interface{}) {
75 item := x.(*job)
Shinichiro Hamajidbc6c132015-04-28 18:26:36 +090076 *jq = append(*jq, item)
77}
78
Fumitoshi Ukaidfb518b2015-06-25 13:19:55 +090079func (jq *jobQueue) Pop() interface{} {
Shinichiro Hamajidbc6c132015-04-28 18:26:36 +090080 old := *jq
81 n := len(old)
82 item := old[n-1]
83 *jq = old[0 : n-1]
84 return item
85}
86
Fumitoshi Ukaidfb518b2015-06-25 13:19:55 +090087func newWorker(wm *workerManager) *worker {
88 w := &worker{
Shinichiro Hamaji69bb7e42015-04-27 17:54:42 +090089 wm: wm,
Fumitoshi Ukaidfb518b2015-06-25 13:19:55 +090090 jobChan: make(chan *job),
Shinichiro Hamaji69bb7e42015-04-27 17:54:42 +090091 waitChan: make(chan bool),
92 doneChan: make(chan bool),
93 }
94 return w
95}
96
Fumitoshi Ukaidfb518b2015-06-25 13:19:55 +090097func (w *worker) Run() {
Shinichiro Hamaji69bb7e42015-04-27 17:54:42 +090098 done := false
99 for !done {
100 select {
101 case j := <-w.jobChan:
102 j.build()
103 w.wm.ReportResult(w, j)
104 case done = <-w.waitChan:
105 }
106 }
107 w.doneChan <- true
108}
109
Fumitoshi Ukaidfb518b2015-06-25 13:19:55 +0900110func (w *worker) PostJob(j *job) {
Shinichiro Hamaji69bb7e42015-04-27 17:54:42 +0900111 w.jobChan <- j
112}
113
Fumitoshi Ukaidfb518b2015-06-25 13:19:55 +0900114func (w *worker) Wait() {
Shinichiro Hamaji69bb7e42015-04-27 17:54:42 +0900115 w.waitChan <- true
116 <-w.doneChan
117}
118
Shinichiro Hamaji74a66002015-04-27 16:42:30 +0900119func evalCmd(ev *Evaluator, r runner, s string) []runner {
120 r = newRunner(r, s)
121 if strings.IndexByte(r.cmd, '$') < 0 {
122 // fast path
123 return []runner{r}
124 }
125 // TODO(ukai): parse once more earlier?
Fumitoshi Ukai7c9aa9f2015-06-12 23:51:38 +0900126 expr, _, err := parseExpr([]byte(r.cmd), nil, false)
Shinichiro Hamaji74a66002015-04-27 16:42:30 +0900127 if err != nil {
128 panic(fmt.Errorf("parse cmd %q: %v", r.cmd, err))
129 }
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900130 buf := newBuf()
131 expr.Eval(buf, ev)
132 cmds := buf.String()
133 freeBuf(buf)
Shinichiro Hamaji74a66002015-04-27 16:42:30 +0900134 var runners []runner
135 for _, cmd := range strings.Split(cmds, "\n") {
Shinichiro Hamaji212abfb2015-04-29 03:02:59 +0900136 if len(runners) > 0 && strings.HasSuffix(runners[len(runners)-1].cmd, "\\") {
137 runners[len(runners)-1].cmd += "\n"
138 runners[len(runners)-1].cmd += cmd
Shinichiro Hamaji74a66002015-04-27 16:42:30 +0900139 } else {
140 runners = append(runners, newRunner(r, cmd))
141 }
142 }
143 return runners
144}
145
146func newRunner(r runner, s string) runner {
147 for {
148 s = trimLeftSpace(s)
149 if s == "" {
150 return runner{}
151 }
152 switch s[0] {
153 case '@':
Fumitoshi Ukai744bb2b2015-06-25 00:10:52 +0900154 if !DryRunFlag {
Shinichiro Hamaji74a66002015-04-27 16:42:30 +0900155 r.echo = false
156 }
157 s = s[1:]
158 continue
159 case '-':
160 r.ignoreError = true
161 s = s[1:]
162 continue
163 }
164 break
165 }
166 r.cmd = s
167 return r
168}
169
170func (r runner) run(output string) error {
Fumitoshi Ukai744bb2b2015-06-25 00:10:52 +0900171 if r.echo || DryRunFlag {
Shinichiro Hamaji74a66002015-04-27 16:42:30 +0900172 fmt.Printf("%s\n", r.cmd)
173 }
Fumitoshi Ukai744bb2b2015-06-25 00:10:52 +0900174 if DryRunFlag {
Shinichiro Hamaji74a66002015-04-27 16:42:30 +0900175 return nil
176 }
177 args := []string{r.shell, "-c", r.cmd}
178 cmd := exec.Cmd{
179 Path: args[0],
180 Args: args,
181 }
182 out, err := cmd.CombinedOutput()
183 fmt.Printf("%s", out)
184 exit := exitStatus(err)
185 if r.ignoreError && exit != 0 {
186 fmt.Printf("[%s] Error %d (ignored)\n", output, exit)
187 err = nil
188 }
189 return err
190}
191
Fumitoshi Ukaidfb518b2015-06-25 13:19:55 +0900192func (j *job) createRunners() []runner {
Shinichiro Hamajib41fd502015-04-29 03:34:07 +0900193 runners, _ := j.ex.createRunners(j.n, false)
Shinichiro Hamaji74a66002015-04-27 16:42:30 +0900194 return runners
195}
196
Shinichiro Hamaji71fae4c2015-05-25 17:48:34 +0900197// TODO(ukai): use time.Time?
198func getTimestamp(filename string) int64 {
199 st, err := os.Stat(filename)
200 if err != nil {
201 return -2
202 }
203 return st.ModTime().Unix()
204}
205
Fumitoshi Ukaidfb518b2015-06-25 13:19:55 +0900206func (j *job) build() {
Shinichiro Hamaji74a66002015-04-27 16:42:30 +0900207 if j.n.IsPhony {
208 j.outputTs = -2 // trigger cmd even if all inputs don't exist.
209 } else {
210 j.outputTs = getTimestamp(j.n.Output)
211 }
212
213 if !j.n.HasRule {
214 if j.outputTs >= 0 || j.n.IsPhony {
Shinichiro Hamaji69bb7e42015-04-27 17:54:42 +0900215 return
Shinichiro Hamaji74a66002015-04-27 16:42:30 +0900216 }
217 if len(j.parents) == 0 {
Fumitoshi Ukai07cf1212015-06-25 17:16:25 +0900218 errorNoLocationExit("*** No rule to make target %q.", j.n.Output)
Shinichiro Hamaji74a66002015-04-27 16:42:30 +0900219 } else {
Fumitoshi Ukai07cf1212015-06-25 17:16:25 +0900220 errorNoLocationExit("*** No rule to make target %q, needed by %q.", j.n.Output, j.parents[0].n.Output)
Shinichiro Hamaji74a66002015-04-27 16:42:30 +0900221 }
Fumitoshi Ukai07cf1212015-06-25 17:16:25 +0900222 errorNoLocationExit("no rule to make target %q", j.n.Output)
Shinichiro Hamaji74a66002015-04-27 16:42:30 +0900223 }
224
225 if j.outputTs >= j.depsTs {
226 // TODO: stats.
Shinichiro Hamaji69bb7e42015-04-27 17:54:42 +0900227 return
Shinichiro Hamaji74a66002015-04-27 16:42:30 +0900228 }
229
230 for _, r := range j.createRunners() {
231 err := r.run(j.n.Output)
232 if err != nil {
233 exit := exitStatus(err)
Fumitoshi Ukai07cf1212015-06-25 17:16:25 +0900234 errorNoLocationExit("[%s] Error %d: %v", j.n.Output, exit, err)
Shinichiro Hamaji74a66002015-04-27 16:42:30 +0900235 }
236 }
237
238 if j.n.IsPhony {
239 j.outputTs = time.Now().Unix()
240 } else {
241 j.outputTs = getTimestamp(j.n.Output)
242 if j.outputTs < 0 {
243 j.outputTs = time.Now().Unix()
244 }
245 }
Shinichiro Hamaji74a66002015-04-27 16:42:30 +0900246}
247
Fumitoshi Ukaidfb518b2015-06-25 13:19:55 +0900248func (wm *workerManager) handleJobs() {
Shinichiro Hamaji69bb7e42015-04-27 17:54:42 +0900249 for {
Fumitoshi Ukai744bb2b2015-06-25 00:10:52 +0900250 if wm.para == nil && len(wm.freeWorkers) == 0 {
Shinichiro Hamaji69bb7e42015-04-27 17:54:42 +0900251 return
252 }
Shinichiro Hamajidbc6c132015-04-28 18:26:36 +0900253 if wm.readyQueue.Len() == 0 {
Shinichiro Hamaji69bb7e42015-04-27 17:54:42 +0900254 return
255 }
Fumitoshi Ukaidfb518b2015-06-25 13:19:55 +0900256 j := heap.Pop(&wm.readyQueue).(*job)
Fumitoshi Ukai07cf1212015-06-25 17:16:25 +0900257 logf("run: %s", j.n.Output)
Shinichiro Hamajicedc5c82015-05-13 17:03:20 +0900258
Fumitoshi Ukai744bb2b2015-06-25 00:10:52 +0900259 if wm.para != nil {
Shinichiro Hamajia6808422015-05-13 18:00:50 +0900260 j.runners = j.createRunners()
261 if len(j.runners) == 0 {
262 wm.updateParents(j)
263 wm.finishCnt++
264 } else {
265 wm.runnings[j.n.Output] = j
266 wm.para.RunCommand(j.runners)
267 }
Shinichiro Hamajicedc5c82015-05-13 17:03:20 +0900268 } else {
269 j.numDeps = -1 // Do not let other workers pick this.
270 w := wm.freeWorkers[0]
271 wm.freeWorkers = wm.freeWorkers[1:]
272 wm.busyWorkers[w] = true
273 w.jobChan <- j
274 }
Shinichiro Hamaji74a66002015-04-27 16:42:30 +0900275 }
Shinichiro Hamaji69bb7e42015-04-27 17:54:42 +0900276}
Shinichiro Hamaji74a66002015-04-27 16:42:30 +0900277
Fumitoshi Ukaidfb518b2015-06-25 13:19:55 +0900278func (wm *workerManager) updateParents(j *job) {
Shinichiro Hamaji74a66002015-04-27 16:42:30 +0900279 for _, p := range j.parents {
280 p.numDeps--
Fumitoshi Ukai07cf1212015-06-25 17:16:25 +0900281 logf("child: %s (%d)", p.n.Output, p.numDeps)
Shinichiro Hamaji74a66002015-04-27 16:42:30 +0900282 if p.depsTs < j.outputTs {
283 p.depsTs = j.outputTs
284 }
Shinichiro Hamajidbc6c132015-04-28 18:26:36 +0900285 wm.maybePushToReadyQueue(p)
Shinichiro Hamaji74a66002015-04-27 16:42:30 +0900286 }
Shinichiro Hamaji74a66002015-04-27 16:42:30 +0900287}
288
Fumitoshi Ukaidfb518b2015-06-25 13:19:55 +0900289type workerManager struct {
Fumitoshi Ukai744bb2b2015-06-25 00:10:52 +0900290 maxJobs int
Fumitoshi Ukaidfb518b2015-06-25 13:19:55 +0900291 jobs []*job
292 readyQueue jobQueue
293 jobChan chan *job
294 resultChan chan jobResult
295 newDepChan chan newDep
Shinichiro Hamaji55c50bd2015-04-27 21:05:47 +0900296 waitChan chan bool
297 doneChan chan bool
Fumitoshi Ukaidfb518b2015-06-25 13:19:55 +0900298 freeWorkers []*worker
299 busyWorkers map[*worker]bool
Shinichiro Hamajicedc5c82015-05-13 17:03:20 +0900300 ex *Executor
Fumitoshi Ukaiff4e5802015-06-25 13:12:26 +0900301 para *paraWorker
302 paraChan chan *paraResult
Fumitoshi Ukaidfb518b2015-06-25 13:19:55 +0900303 runnings map[string]*job
Shinichiro Hamajidbc6c132015-04-28 18:26:36 +0900304
305 finishCnt int
Shinichiro Hamaji74a66002015-04-27 16:42:30 +0900306}
307
Fumitoshi Ukaidfb518b2015-06-25 13:19:55 +0900308func newWorkerManager(numJobs int, paraPath string) *workerManager {
309 wm := &workerManager{
Fumitoshi Ukai744bb2b2015-06-25 00:10:52 +0900310 maxJobs: numJobs,
Fumitoshi Ukaidfb518b2015-06-25 13:19:55 +0900311 jobChan: make(chan *job),
312 resultChan: make(chan jobResult),
313 newDepChan: make(chan newDep),
Shinichiro Hamaji55c50bd2015-04-27 21:05:47 +0900314 waitChan: make(chan bool),
315 doneChan: make(chan bool),
Fumitoshi Ukaidfb518b2015-06-25 13:19:55 +0900316 busyWorkers: make(map[*worker]bool),
Shinichiro Hamaji69bb7e42015-04-27 17:54:42 +0900317 }
Shinichiro Hamajicedc5c82015-05-13 17:03:20 +0900318
Fumitoshi Ukai744bb2b2015-06-25 00:10:52 +0900319 if paraPath != "" {
Fumitoshi Ukaidfb518b2015-06-25 13:19:55 +0900320 wm.runnings = make(map[string]*job)
Fumitoshi Ukaiff4e5802015-06-25 13:12:26 +0900321 wm.paraChan = make(chan *paraResult)
Fumitoshi Ukai744bb2b2015-06-25 00:10:52 +0900322 wm.para = newParaWorker(wm.paraChan, numJobs, paraPath)
Shinichiro Hamajicedc5c82015-05-13 17:03:20 +0900323 go wm.para.Run()
324 } else {
Fumitoshi Ukaidfb518b2015-06-25 13:19:55 +0900325 wm.busyWorkers = make(map[*worker]bool)
Fumitoshi Ukai744bb2b2015-06-25 00:10:52 +0900326 for i := 0; i < numJobs; i++ {
327 w := newWorker(wm)
Shinichiro Hamajicedc5c82015-05-13 17:03:20 +0900328 wm.freeWorkers = append(wm.freeWorkers, w)
329 go w.Run()
330 }
Shinichiro Hamaji74a66002015-04-27 16:42:30 +0900331 }
Shinichiro Hamajicedc5c82015-05-13 17:03:20 +0900332 heap.Init(&wm.readyQueue)
Shinichiro Hamaji74a66002015-04-27 16:42:30 +0900333 go wm.Run()
334 return wm
335}
336
337func exitStatus(err error) int {
338 if err == nil {
339 return 0
340 }
341 exit := 1
342 if err, ok := err.(*exec.ExitError); ok {
343 if w, ok := err.ProcessState.Sys().(syscall.WaitStatus); ok {
344 return w.ExitStatus()
345 }
346 }
347 return exit
348}
349
Fumitoshi Ukaidfb518b2015-06-25 13:19:55 +0900350func (wm *workerManager) hasTodo() bool {
Shinichiro Hamajidbc6c132015-04-28 18:26:36 +0900351 return wm.finishCnt != len(wm.jobs)
352}
353
Fumitoshi Ukaidfb518b2015-06-25 13:19:55 +0900354func (wm *workerManager) maybePushToReadyQueue(j *job) {
Shinichiro Hamajidbc6c132015-04-28 18:26:36 +0900355 if j.numDeps != 0 {
356 return
Shinichiro Hamaji69bb7e42015-04-27 17:54:42 +0900357 }
Shinichiro Hamajidbc6c132015-04-28 18:26:36 +0900358 heap.Push(&wm.readyQueue, j)
Fumitoshi Ukai07cf1212015-06-25 17:16:25 +0900359 logf("ready: %s", j.n.Output)
Shinichiro Hamaji69bb7e42015-04-27 17:54:42 +0900360}
361
Fumitoshi Ukaidfb518b2015-06-25 13:19:55 +0900362func (wm *workerManager) handleNewDep(j *job, neededBy *job) {
Shinichiro Hamaji69bb7e42015-04-27 17:54:42 +0900363 if j.numDeps < 0 {
364 neededBy.numDeps--
Shinichiro Hamaji5180c972015-04-28 20:14:38 +0900365 if neededBy.id > 0 {
366 panic("already in WM... can this happen?")
Shinichiro Hamaji5180c972015-04-28 20:14:38 +0900367 }
Shinichiro Hamaji69bb7e42015-04-27 17:54:42 +0900368 } else {
369 j.parents = append(j.parents, neededBy)
370 }
371}
372
Fumitoshi Ukaidfb518b2015-06-25 13:19:55 +0900373func (wm *workerManager) Run() {
Shinichiro Hamaji74a66002015-04-27 16:42:30 +0900374 done := false
Shinichiro Hamajicedc5c82015-05-13 17:03:20 +0900375 for wm.hasTodo() || len(wm.busyWorkers) > 0 || len(wm.runnings) > 0 || !done {
Shinichiro Hamaji74a66002015-04-27 16:42:30 +0900376 select {
377 case j := <-wm.jobChan:
Fumitoshi Ukai07cf1212015-06-25 17:16:25 +0900378 logf("wait: %s (%d)", j.n.Output, j.numDeps)
Shinichiro Hamaji5180c972015-04-28 20:14:38 +0900379 j.id = len(wm.jobs) + 1
Shinichiro Hamaji69bb7e42015-04-27 17:54:42 +0900380 wm.jobs = append(wm.jobs, j)
Shinichiro Hamajidbc6c132015-04-28 18:26:36 +0900381 wm.maybePushToReadyQueue(j)
Shinichiro Hamaji69bb7e42015-04-27 17:54:42 +0900382 case jr := <-wm.resultChan:
Fumitoshi Ukai07cf1212015-06-25 17:16:25 +0900383 logf("done: %s", jr.j.n.Output)
Shinichiro Hamaji69bb7e42015-04-27 17:54:42 +0900384 delete(wm.busyWorkers, jr.w)
385 wm.freeWorkers = append(wm.freeWorkers, jr.w)
386 wm.updateParents(jr.j)
Shinichiro Hamajidbc6c132015-04-28 18:26:36 +0900387 wm.finishCnt++
Shinichiro Hamaji55c50bd2015-04-27 21:05:47 +0900388 case af := <-wm.newDepChan:
389 wm.handleNewDep(af.j, af.neededBy)
Fumitoshi Ukai07cf1212015-06-25 17:16:25 +0900390 logf("dep: %s (%d) %s", af.neededBy.n.Output, af.neededBy.numDeps, af.j.n.Output)
Shinichiro Hamajicedc5c82015-05-13 17:03:20 +0900391 case pr := <-wm.paraChan:
Shinichiro Hamajia6808422015-05-13 18:00:50 +0900392 if pr.status < 0 && pr.signal < 0 {
393 j := wm.runnings[pr.output]
394 for _, r := range j.runners {
Fumitoshi Ukai744bb2b2015-06-25 00:10:52 +0900395 if r.echo || DryRunFlag {
Shinichiro Hamajia6808422015-05-13 18:00:50 +0900396 fmt.Printf("%s\n", r.cmd)
397 }
398 }
399 } else {
Fumitoshi Ukai145598a2015-06-19 10:08:17 +0900400 fmt.Fprint(os.Stdout, pr.stdout)
401 fmt.Fprint(os.Stderr, pr.stderr)
Shinichiro Hamajia6808422015-05-13 18:00:50 +0900402 j := wm.runnings[pr.output]
403 wm.updateParents(j)
404 delete(wm.runnings, pr.output)
405 wm.finishCnt++
406 }
Shinichiro Hamaji74a66002015-04-27 16:42:30 +0900407 case done = <-wm.waitChan:
408 }
Shinichiro Hamaji69bb7e42015-04-27 17:54:42 +0900409 wm.handleJobs()
Shinichiro Hamajicedc5c82015-05-13 17:03:20 +0900410
Fumitoshi Ukai744bb2b2015-06-25 00:10:52 +0900411 if wm.para != nil {
Shinichiro Hamajicedc5c82015-05-13 17:03:20 +0900412 numBusy := len(wm.runnings)
Fumitoshi Ukai744bb2b2015-06-25 00:10:52 +0900413 if numBusy > wm.maxJobs {
414 numBusy = wm.maxJobs
Shinichiro Hamajicedc5c82015-05-13 17:03:20 +0900415 }
Fumitoshi Ukai07cf1212015-06-25 17:16:25 +0900416 logf("job=%d ready=%d free=%d busy=%d", len(wm.jobs)-wm.finishCnt, wm.readyQueue.Len(), wm.maxJobs-numBusy, numBusy)
Shinichiro Hamajicedc5c82015-05-13 17:03:20 +0900417 } else {
Fumitoshi Ukai07cf1212015-06-25 17:16:25 +0900418 logf("job=%d ready=%d free=%d busy=%d", len(wm.jobs)-wm.finishCnt, wm.readyQueue.Len(), len(wm.freeWorkers), len(wm.busyWorkers))
Shinichiro Hamajicedc5c82015-05-13 17:03:20 +0900419 }
Shinichiro Hamaji69bb7e42015-04-27 17:54:42 +0900420 }
421
Fumitoshi Ukai744bb2b2015-06-25 00:10:52 +0900422 if wm.para != nil {
Fumitoshi Ukai07cf1212015-06-25 17:16:25 +0900423 logf("Wait for para to finish")
Shinichiro Hamajicedc5c82015-05-13 17:03:20 +0900424 wm.para.Wait()
425 } else {
426 for _, w := range wm.freeWorkers {
427 w.Wait()
428 }
429 for w := range wm.busyWorkers {
430 w.Wait()
431 }
Shinichiro Hamaji74a66002015-04-27 16:42:30 +0900432 }
433 wm.doneChan <- true
434}
435
Fumitoshi Ukaidfb518b2015-06-25 13:19:55 +0900436func (wm *workerManager) PostJob(j *job) {
Shinichiro Hamaji74a66002015-04-27 16:42:30 +0900437 wm.jobChan <- j
438}
439
Fumitoshi Ukaidfb518b2015-06-25 13:19:55 +0900440func (wm *workerManager) ReportResult(w *worker, j *job) {
441 wm.resultChan <- jobResult{w: w, j: j}
Shinichiro Hamaji69bb7e42015-04-27 17:54:42 +0900442}
443
Fumitoshi Ukaidfb518b2015-06-25 13:19:55 +0900444func (wm *workerManager) ReportNewDep(j *job, neededBy *job) {
445 wm.newDepChan <- newDep{j: j, neededBy: neededBy}
Shinichiro Hamaji69bb7e42015-04-27 17:54:42 +0900446}
447
Fumitoshi Ukaidfb518b2015-06-25 13:19:55 +0900448func (wm *workerManager) Wait() {
Shinichiro Hamaji74a66002015-04-27 16:42:30 +0900449 wm.waitChan <- true
450 <-wm.doneChan
451}