github.com/omniscale/go-osm@v0.3.1/parser/pbf/barrier.go (about)

     1  package pbf
     2  
     3  import (
     4  	"sync"
     5  	"sync/atomic"
     6  )
     7  
     8  // barrier is a struct to synchronize multiple goroutines.
     9  // Works similar to a WaitGroup. Except:
    10  // Calls callback function once all goroutines called doneWait().
    11  // doneWait() blocks until the callback returns. doneWait() does not
    12  // block after all goroutines were blocked once.
    13  type barrier struct {
    14  	synced     int32
    15  	wg         sync.WaitGroup
    16  	once       sync.Once
    17  	callbackWg sync.WaitGroup
    18  	callback   func()
    19  }
    20  
    21  func newBarrier(callback func()) *barrier {
    22  	s := &barrier{callback: callback}
    23  	s.callbackWg.Add(1)
    24  	return s
    25  }
    26  
    27  func (s *barrier) add(delta int) {
    28  	s.wg.Add(delta)
    29  }
    30  
    31  func (s *barrier) doneWait() {
    32  	if atomic.LoadInt32(&s.synced) == 1 {
    33  		return
    34  	}
    35  	s.wg.Done()
    36  	s.wg.Wait()
    37  	s.once.Do(s.call)
    38  	s.callbackWg.Wait()
    39  }
    40  
    41  func (s *barrier) call() {
    42  	s.callback()
    43  	atomic.StoreInt32(&s.synced, 1)
    44  	s.callbackWg.Done()
    45  }