// Copyright (C) 2019 Storj Labs, Inc. // See LICENSE for copying information package sync2 import ( "context" "sync" ) // Fence allows to wait for something to happen. type Fence struct { noCopy noCopy // nolint: structcheck setup sync.Once release sync.Once done chan struct{} } // init sets up the initial lock into wait. func (fence *Fence) init() { fence.setup.Do(func() { fence.done = make(chan struct{}) }) } // Release releases everyone from Wait. func (fence *Fence) Release() { fence.init() fence.release.Do(func() { close(fence.done) }) } // Wait waits for wait to be unlocked. // Returns true when it was successfully released. func (fence *Fence) Wait(ctx context.Context) bool { fence.init() select { case <-fence.done: return true default: select { case <-ctx.Done(): return false case <-fence.done: return true } } } // Released returns whether the fence has been released. func (fence *Fence) Released() bool { fence.init() select { case <-fence.done: return true default: return false } } // Done returns channel that will be closed when the fence is released. func (fence *Fence) Done() chan struct{} { fence.init() return fence.done }