blob: 3b99e0ffe621b8a61d35f9fc432d10a93706944f [file] [log] [blame]
// Copyright 2015 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package discovery
import "sync"
// A Barrier is a simple incremental barrier that runs a done closure after
// all closures returned by Add() have been invoked. The done closure will
// run only once and run in a separate goroutine.
type Barrier struct {
mu sync.Mutex
n int // GUARDED_BY(mu)
done func()
}
// Add increments the barrier. Each closure returned by Add() should eventually
// be run once, otherwise 'done' will never be run. It returns nil if the done
// closure has been already called.
func (b *Barrier) Add() func() {
b.mu.Lock()
if b.done == nil {
b.mu.Unlock()
return nil
}
b.n++
b.mu.Unlock()
return b.run
}
func (b *Barrier) run() {
b.mu.Lock()
b.n--
if b.n > 0 {
b.mu.Unlock()
return
}
done := b.done
b.done = nil
b.mu.Unlock()
if done != nil {
go done()
}
}
func NewBarrier(done func()) *Barrier {
return &Barrier{done: done}
}