func (tasks Tasks) RunTasksWithTimeout(stopTime time.Time) {
	finishedTasks := 0
	waitCond := new(sync.Cond)
	waitCond.L = new(sync.Mutex)

	done := make(chan bool, 1)
	current_running := 0
	for _, task := range tasks {

		waitCond.L.Lock()
		for current_running >= numWorkers {
			waitCond.Wait()
		}
		current_running++
		waitCond.L.Unlock()

		go func(task *Task) {
			todo := len(tasks) - finishedTasks - (numWorkers - 1)
			if todo < 1 {
				todo = 1
			}
			duration := stopTime.Sub(time.Now()) / time.Duration(todo)
			dprint(duration)
			task.stopTime = time.Now().Add(duration)
			go task.Run()
			<-task.ch
			if task.timed_out {
				dprint("Timeout occured.")
			} else {
				dprint("Finished normally.")
			}

			waitCond.L.Lock()
			current_running--
			finishedTasks++
			if finishedTasks == len(tasks) {
				done <- true
			}
			waitCond.Signal()
			waitCond.L.Unlock()
		}(task)
	}
	<-done
}
Exemple #2
0
func main() {
	runtime.GOMAXPROCS(1)
	debug.SetGCPercent(1000000) // only GC when we ask for GC

	var stats, stats1, stats2 runtime.MemStats

	release := func() {}
	for i := 0; i < 20; i++ {
		if i == 10 {
			// Should be warmed up by now.
			runtime.ReadMemStats(&stats1)
		}

		c := make(chan int)
		for i := 0; i < 10; i++ {
			go func() {
				select {
				case <-c:
				case <-c:
				case <-c:
				}
			}()
		}
		time.Sleep(1 * time.Millisecond)
		release()

		close(c) // let select put its sudog's into the cache
		time.Sleep(1 * time.Millisecond)

		// pick up top sudog
		var cond1 sync.Cond
		var mu1 sync.Mutex
		cond1.L = &mu1
		go func() {
			mu1.Lock()
			cond1.Wait()
			mu1.Unlock()
		}()
		time.Sleep(1 * time.Millisecond)

		// pick up next sudog
		var cond2 sync.Cond
		var mu2 sync.Mutex
		cond2.L = &mu2
		go func() {
			mu2.Lock()
			cond2.Wait()
			mu2.Unlock()
		}()
		time.Sleep(1 * time.Millisecond)

		// put top sudog back
		cond1.Broadcast()
		time.Sleep(1 * time.Millisecond)

		// drop cache on floor
		runtime.GC()

		// release cond2 after select has gotten to run
		release = func() {
			cond2.Broadcast()
			time.Sleep(1 * time.Millisecond)
		}
	}

	runtime.GC()

	runtime.ReadMemStats(&stats2)

	if int(stats2.HeapObjects)-int(stats1.HeapObjects) > 20 { // normally at most 1 or 2; was 300 with leak
		print("BUG: object leak: ", stats.HeapObjects, " -> ", stats1.HeapObjects, " -> ", stats2.HeapObjects, "\n")
	}
}