package main
func routine(quit chan int) {
// do stuff
quit <- 1
}
func main() {
routineQuit := make(chan int)
go routine(routineQuit)
<-routineQuit // blocks until quit is written to
}
-Daniel
> Since I launch many goroutines using a for loop, I use the following
> construction for waiting them to end:
>
> for j := 0; j < *concurrency; _, j = <- sem, j+1 { }
>
> I just wanted to know if this was the best way for doing this, although I
> have to say that I'm missing the wait() system call.
It depends on the rest of your program, of course, but looping until
you've read a value from each goroutine is perfectly reasonable. That
actual code won't work in Go because of the comma, and reading a value
from the channel and using that in the loop seems odd.
Ian
http://michaelspeer.blogspot.com/2010/03/go-language-is-lovely.html
//// "dispatch.go"
package dispatch
import "sync"
type Manager interface {
Go( func() )
Wait()
}
type manager struct {
lock sync.Mutex
running uint
waiting uint
wakeup chan bool
}
func New() *manager {
m := new(manager)
m.wakeup = make(chan bool)
return m
}
func (m *manager) Go( fn func() ) {
m.lock.Lock()
m.running++
m.lock.Unlock()
go func(){
fn()
m.lock.Lock()
m.running--
if (m.running == 0) && (m.waiting > 0) {
oc := m.wakeup
nc := make(chan bool)
i := m.waiting
go func(){
for ; i > 0 ; i-- {
oc <- true
}
}()
m.wakeup = nc
m.waiting = 0
}
m.lock.Unlock()
}()
}
func (m *manager) Wait() {
wait := false
m.lock.Lock()
if m.running > 0 {
m.waiting++
wait = true
}
m.lock.Unlock()
if wait {
<- m.wakeup
}
}
//// "main.go" //// some example usage
package main
import "fmt"
import "rand"
import "time"
import "./dispatch"
func main () {
w := dispatch.New()
for i := 0 ; i < 100 ; i++ {
c := i
w.Go( func(){
time.Sleep( rand.Int63n( 1000000000 ) )
fmt.Print( c , "\n" )
w.Go( func(){
time.Sleep( rand.Int63n( 1000000000 ) )
fmt.Print( c , " - second effect\n")
})
})
}
fmt.Print( "All Launched\n" )
w2 := dispatch.New()
for i := 0 ; i < 5 ; i++ {
c := i
w2.Go( func(){
w.Wait()
time.Sleep( rand.Int63n( 1000000000 ) )
fmt.Print("[ " , c , "] This should happen
after the first set\n")
})
}
fmt.Print( "Second set all launched\n" )
w.Wait()
for i := 10 ; i < 15 ; i++ {
c := i
w.Go( func(){
time.Sleep( rand.Int63n( 1000000000 ) )
fmt.Print("[ " , c , "] reusing first queue\n")
})
}
fmt.Print( "Main thread past first set\n" )
w2.Wait()
fmt.Print( "Main thread past second set\n" )
w.Wait()
fmt.Print( "Main thread past reuse of first queue\n" )
}
your code looks pretty good though. i've made a few comments
on your blog page.