Skip to content

Instantly share code, notes, and snippets.

@umit
Last active April 9, 2021 10:27
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save umit/77d3411a85f02b6a1589f93ad02cac9e to your computer and use it in GitHub Desktop.
Save umit/77d3411a85f02b6a1589f93ad02cac9e to your computer and use it in GitHub Desktop.
count_down_latch
type CountDownLatch struct {
sync.WaitGroup
counter uint64
}
func (cdl *CountDownLatch) Add(delta int) {
cdl.WaitGroup.Add(delta)
d := uint32(delta)
atomic.AddUint64(&cdl.counter, combineUInt64For(d, d))
}
func (cdl *CountDownLatch) Done() {
c := atomic.LoadUint64(&cdl.counter)
hc, lc := splitUint64For(c)
for hc > 0 {
if atomic.CompareAndSwapUint64(&cdl.counter, c, combineUInt64For(hc-1, lc-1)) {
cdl.WaitGroup.Done()
return
}
c = atomic.LoadUint64(&cdl.counter)
hc, lc = splitUint64For(c)
}
}
func (cdl *CountDownLatch) Await(t time.Duration) bool {
time.AfterFunc(t, func() {
c := atomic.LoadUint64(&cdl.counter)
hc, lc := splitUint64For(c)
for hc > 0 {
if atomic.CompareAndSwapUint64(&cdl.counter, c, combineUInt64For(0, lc)) {
cdl.WaitGroup.Add(-int(hc))
break
}
c = atomic.LoadUint64(&cdl.counter)
hc, lc = splitUint64For(c)
}
})
cdl.Wait()
return atomic.LoadUint64(&cdl.counter) == 0
}
func splitUint64For(c uint64) (uint32, uint32) {
return uint32(c >> 32), uint32(c)
}
func combineUInt64For(x, y uint32) uint64 {
return uint64(x)<<32 | uint64(y)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment