cloudflare/cloudflared
Publicmirrored from https://github.com/cloudflare/cloudflaredAvailable
h2mux/booleanfuse.go
50lines · modecode
| 1 | package h2mux |
| 2 | |
| 3 | import "sync" |
| 4 | |
| 5 | // BooleanFuse is a data structure that can be set once to a particular value using Fuse(value). |
| 6 | // Subsequent calls to Fuse() will have no effect. |
| 7 | type BooleanFuse struct { |
| 8 | value int32 |
| 9 | mu sync.Mutex |
| 10 | cond *sync.Cond |
| 11 | } |
| 12 | |
| 13 | func NewBooleanFuse() *BooleanFuse { |
| 14 | f := &BooleanFuse{} |
| 15 | f.cond = sync.NewCond(&f.mu) |
| 16 | return f |
| 17 | } |
| 18 | |
| 19 | // Value gets the value |
| 20 | func (f *BooleanFuse) Value() bool { |
| 21 | // 0: unset |
| 22 | // 1: set true |
| 23 | // 2: set false |
| 24 | f.mu.Lock() |
| 25 | defer f.mu.Unlock() |
| 26 | return f.value == 1 |
| 27 | } |
| 28 | |
| 29 | func (f *BooleanFuse) Fuse(result bool) { |
| 30 | f.mu.Lock() |
| 31 | defer f.mu.Unlock() |
| 32 | newValue := int32(2) |
| 33 | if result { |
| 34 | newValue = 1 |
| 35 | } |
| 36 | if f.value == 0 { |
| 37 | f.value = newValue |
| 38 | f.cond.Broadcast() |
| 39 | } |
| 40 | } |
| 41 | |
| 42 | // Await blocks until Fuse has been called at least once. |
| 43 | func (f *BooleanFuse) Await() bool { |
| 44 | f.mu.Lock() |
| 45 | defer f.mu.Unlock() |
| 46 | for f.value == 0 { |
| 47 | f.cond.Wait() |
| 48 | } |
| 49 | return f.value == 1 |
| 50 | } |
| 51 | |