github.com/docker/compose-on-kubernetes@v0.5.0/internal/deduplication/stringchannel.go (about) 1 package deduplication 2 3 import "sync" 4 5 // StringChan is a deduplicating string channel 6 type StringChan struct { 7 mut sync.Mutex 8 content map[string]struct{} 9 ch chan string 10 input chan string 11 output chan string 12 } 13 14 // NewStringChan creates a StringChan with the specified buffer size 15 func NewStringChan(bufferSize int) *StringChan { 16 result := &StringChan{ch: make(chan string, bufferSize), content: make(map[string]struct{}, bufferSize+1), input: make(chan string), output: make(chan string)} 17 go func() { 18 defer close(result.ch) 19 for v := range result.input { 20 result.push(v) 21 } 22 }() 23 go func() { 24 defer close(result.output) 25 for { 26 v, ok := result.pull() 27 if !ok { 28 return 29 } 30 result.output <- v 31 } 32 }() 33 return result 34 } 35 36 // Close releases all resources 37 func (c *StringChan) Close() { 38 close(c.input) 39 } 40 41 // Push pushes a value if it is not in the buffer 42 func (c *StringChan) push(v string) { 43 added := func() bool { 44 c.mut.Lock() 45 defer c.mut.Unlock() 46 if _, ok := c.content[v]; ok { 47 return false 48 } 49 c.content[v] = struct{}{} 50 return true 51 }() 52 if added { 53 c.ch <- v 54 } 55 } 56 57 // Pull consumes a value 58 func (c *StringChan) pull() (string, bool) { 59 v, ok := <-c.ch 60 c.mut.Lock() 61 defer c.mut.Unlock() 62 delete(c.content, v) 63 return v, ok 64 } 65 66 // In returns the input channel of the deduplicator 67 func (c *StringChan) In() chan<- string { 68 return c.input 69 } 70 71 // Out returns the output channel of the deduplicator 72 func (c *StringChan) Out() <-chan string { 73 return c.output 74 }