Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

sync: return true from the last WaitGroup.Done #7019

Closed
dvyukov opened this issue Dec 27, 2013 · 3 comments
Closed

sync: return true from the last WaitGroup.Done #7019

dvyukov opened this issue Dec 27, 2013 · 3 comments
Labels
FrozenDueToAge v2 A language change or incompatible library change

Comments

@dvyukov
Copy link
Member

dvyukov commented Dec 27, 2013

Frequently when you are using WaitGroup you do:

    var wg sync.WaitGroup
    wg.Add(N)
    for i := 0; i < N; i++ {
        go func() {
            for v := range in {
                out <- v * v
            }
            wg.Done()
        }()
    }
    go func() {
        wg.Wait()
        close(out)
    }()

It would be nice to do it w/o the helper goroutine:

    var wg sync.WaitGroup
    wg.Add(N)
    for i := 0; i < N; i++ {
        go func() {
            for v := range in {
                out <- v * v
            }
            if wg.Done() {
                close(out)
            }
        }()
    }

I.e. WaitGroup.Done/Add return true when the counter drops to zero.
This breaks backward compatibility (var f func() = wg.Done), so marking "Go2".
@dominikh
Copy link
Member

Comment 1:

I'm worried that will lead to people write racy code such as the following:
var wg sync.WaitGroup
for i := 0; i < N; i {
    wg.Add(1)
    go func() {
        ...
        if wg.Done() { 
            close(out) 
        }
    }
}

@dvyukov
Copy link
Member Author

dvyukov commented Dec 27, 2013

Comment 2:

You are right!

Status changed to WorkingAsIntended.

@egonelbre
Copy link
Contributor

Comment 3:

This frequent can be remedied with a function:
func Spawn(N int32, fn func(id int), autoclose ...interface{}) {
    var counter int32 = N
    for k := 0; k < int(N); k += 1 {
        go func(k int) {
            fn(k)
            if atomic.AddInt32(&counter, -1) == 0 {
                for _, ch := range autoclose {
                    reflect.ValueOf(ch).Close()
                }
            }
        }(k)
    }
}
And the usage example: http://play.golang.org/p/8M156uFYPW.
Alternatively, the last parameter can be a callback to cleanup:
func Spawn(N int32, fn func(id int), whendone ...func()) {
    var counter int32 = N
    for k := 0; k < int(N); k += 1 {
        go func(k int) {
            fn(k)
            if atomic.AddInt32(&counter, -1) == 0 {
                for _, fn := range whendone {
                    fn()
                }
            }
        }(k)
    }
}

@dvyukov dvyukov added workingasintended v2 A language change or incompatible library change labels Dec 27, 2013
@golang golang locked and limited conversation to collaborators Jun 25, 2016
This issue was closed.
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
FrozenDueToAge v2 A language change or incompatible library change
Projects
None yet
Development

No branches or pull requests

4 participants