On Sun, May 5, 2019 at 12:45 PM Louki Sumirniy
<louki.sumirniy.stal...@gmail.com> wrote:
>
> https://play.golang.org/p/5KwJQcTsUPg
>
> I fixed it.

Not really. You've introduced a data race.

jnml@4670:~/src/tmp> cat main.go
package main

type WaitGroup struct {
        workers int
        ops     chan int
}

func New() *WaitGroup {
        wg := new(WaitGroup)
        return wg
}

func startWait(wg *WaitGroup) {
        wg.ops = make(chan int)

        go func() {
                done := false
                for !done {
                        select {
                        case op := <-wg.ops:
                                wg.workers += op
                                if wg.workers < 1 {
                                        done = true
                                        close(wg.ops)
                                }
                        }
                }
        }()
}

// Add adds a non-negative number
func (wg *WaitGroup) Add(delta int) {
        if delta < 0 {
                return
        }
        if wg.ops == nil {
                startWait(wg)
        }
        wg.ops <- delta
}

// Done subtracts a non-negative value from the workers count
func (wg *WaitGroup) Done(delta int) {
        if delta < 0 {
                return
        }
        wg.ops <- -delta
}

// Wait blocks until the waitgroup decrements to zero
func (wg *WaitGroup) Wait() {
        for {
                if wg.workers < 1 {
                        break
                }
                op, ok := <-wg.ops
                if !ok {
                        break
                } else {
                        wg.ops <- op
                }
        }
}

var wg = New()

func main() {
        for i := 0; i < 2; i++ {
                wg.Add(1)
                go f()
        }
        wg.Wait()
}

func f() {
        defer wg.Done(1)

        for i := 0; i < 2; i++ {
                wg.Add(1)
                go g()
        }
}

func g() { wg.Done(1) }
jnml@4670:~/src/tmp> go run -race main.go
==================
WARNING: DATA RACE
Read at 0x00c00008a000 by main goroutine:
  main.(*WaitGroup).Wait()
      /home/jnml/src/tmp/main.go:53 +0x6f
  main.main()
      /home/jnml/src/tmp/main.go:72 +0x104

Previous write at 0x00c00008a000 by goroutine 5:
  main.startWait.func1()
      /home/jnml/src/tmp/main.go:21 +0xbb

Goroutine 5 (running) created at:
  main.startWait()
      /home/jnml/src/tmp/main.go:16 +0x9e
  main.main()
      /home/jnml/src/tmp/main.go:37 +0xdf
==================
Found 1 data race(s)
exit status 66
jnml@4670:~/src/tmp>

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to