package main

import "time"
import "log"
import "fmt"

var delayA uint = 3
var delayB uint = 3

func longCalc(x int, delay uint) int {
	log.Println("calc", x)
	time.Sleep(time.Duration(delay) * time.Second)
	log.Println("done", x)
	return x
}

func longCalcAsync(x int, delay uint) (chan int) {
	result := make(chan int)
	go func() {
		result <- longCalc(x, delay)
	}()
	return result
}

func bar() {
	log.Println("bar")
}

// --------------------------------



func foo1() {
	a := <- longCalcAsync(1, delayA)
	b := <- longCalcAsync(2, delayB)
	log.Println("foo", a, b)
}

func foo2() {
	ca := longCalcAsync(1, delayA)
	cb := longCalcAsync(2, delayB)
	a := <- ca
	b := <- cb
	log.Println("foo", a, b)
}

func foo3a() {
	a := longCalc(1, delayA)
	b := longCalc(2, delayB)
	log.Println("foo", a, b)
}

func foo3b() (chan bool) {
	done := make(chan bool)
	go func() {
		foo3a()
		done <- true
	}()
	return done
}

// --------------------------------



func test1() {
	go foo1()
	bar()
	time.Sleep(10 * time.Second)
}

func test2() {
	go foo2()
	bar()
	time.Sleep(10 * time.Second)
}

func test3a() {
	go foo3a()
	bar()
	time.Sleep(10 * time.Second)
}

func test3b() {
	done := foo3b()
	bar()
	<- done
}

// --------------------------------



func init() {
	log.SetFlags(log.Ltime)
}

func main() {
	test1()
	fmt.Println("--------")
	test2()
	fmt.Println("--------")
	test3a()
	fmt.Println("--------")
	test3b()
}