github.com/iaintshine/docker@v1.8.2/pkg/broadcastwriter/broadcastwriter.go (about) 1 package broadcastwriter 2 3 import ( 4 "io" 5 "sync" 6 ) 7 8 // BroadcastWriter accumulate multiple io.WriteCloser by stream. 9 type BroadcastWriter struct { 10 sync.Mutex 11 writers map[io.WriteCloser]struct{} 12 } 13 14 // AddWriter adds new io.WriteCloser. 15 func (w *BroadcastWriter) AddWriter(writer io.WriteCloser) { 16 w.Lock() 17 w.writers[writer] = struct{}{} 18 w.Unlock() 19 } 20 21 // Write writes bytes to all writers. Failed writers will be evicted during 22 // this call. 23 func (w *BroadcastWriter) Write(p []byte) (n int, err error) { 24 w.Lock() 25 for sw := range w.writers { 26 if n, err := sw.Write(p); err != nil || n != len(p) { 27 // On error, evict the writer 28 delete(w.writers, sw) 29 } 30 } 31 w.Unlock() 32 return len(p), nil 33 } 34 35 // Clean closes and removes all writers. Last non-eol-terminated part of data 36 // will be saved. 37 func (w *BroadcastWriter) Clean() error { 38 w.Lock() 39 for w := range w.writers { 40 w.Close() 41 } 42 w.writers = make(map[io.WriteCloser]struct{}) 43 w.Unlock() 44 return nil 45 } 46 47 func New() *BroadcastWriter { 48 return &BroadcastWriter{ 49 writers: make(map[io.WriteCloser]struct{}), 50 } 51 }