forked from ianlopshire/go-async
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlatch.go
60 lines (50 loc) · 1.09 KB
/
latch.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
package async
import (
"sync"
)
// closedchan is a reusable closed channel.
var closedchan = make(chan struct{})
func init() {
close(closedchan)
}
// Latch is a synchronization primitive that can be used to block until a desired state is
// reached.
//
// The zero value for Latch is in an open (blocking) state. Use the package level Resolve
// function to resolve a Latch. Once resolved, the Latch cannot be reopened.
//
// Attempting to resolve a Latch more than once will panic with ErrAlreadyResolved.
//
// A Latch must not be copied after first use.
type Latch struct {
mu sync.Mutex
done chan struct{}
}
// Done returns a channel that will be closed when the Latch is resolved.
func (l *Latch) Done() <-chan struct{} {
l.mu.Lock()
if l.done == nil {
l.done = make(chan struct{})
}
d := l.done
l.mu.Unlock()
return d
}
func (l *Latch) resolve(fn func()) {
l.mu.Lock()
defer l.mu.Unlock()
if fn != nil {
fn()
}
if l.done == nil {
l.done = closedchan
return
}
select {
case <-l.done:
panic(ErrAlreadyResolved)
default:
// Intentionally left blank.
}
close(l.done)
}