1
0
Fork 0
mirror of https://github.com/moby/moby.git synced 2022-11-09 12:21:53 -05:00

Swapped a map for a list in writeBroadcaster.

This commit is contained in:
Robert Obryk 2013-03-30 14:44:00 +01:00
parent 0bdfcfaa33
commit 75ba07cb3a

View file

@ -2,7 +2,6 @@ package docker
import ( import (
"bytes" "bytes"
"container/list"
"errors" "errors"
"fmt" "fmt"
"github.com/dotcloud/docker/rcli" "github.com/dotcloud/docker/rcli"
@ -214,12 +213,12 @@ func (r *bufReader) Close() error {
type writeBroadcaster struct { type writeBroadcaster struct {
mu sync.Mutex mu sync.Mutex
writers *list.List writers map[io.WriteCloser]struct{}
} }
func (w *writeBroadcaster) AddWriter(writer io.WriteCloser) { func (w *writeBroadcaster) AddWriter(writer io.WriteCloser) {
w.mu.Lock() w.mu.Lock()
w.writers.PushBack(writer) w.writers[writer] = struct{}{}
w.mu.Unlock() w.mu.Unlock()
} }
@ -227,46 +226,32 @@ func (w *writeBroadcaster) AddWriter(writer io.WriteCloser) {
// FIXME: This relies on the concrete writer type used having equality operator // FIXME: This relies on the concrete writer type used having equality operator
func (w *writeBroadcaster) RemoveWriter(writer io.WriteCloser) { func (w *writeBroadcaster) RemoveWriter(writer io.WriteCloser) {
w.mu.Lock() w.mu.Lock()
defer w.mu.Unlock() delete(w.writers, writer)
for e := w.writers.Front(); e != nil; e = e.Next() { w.mu.Unlock()
v := e.Value.(io.Writer)
if v == writer {
w.writers.Remove(e)
return
}
}
} }
func (w *writeBroadcaster) Write(p []byte) (n int, err error) { func (w *writeBroadcaster) Write(p []byte) (n int, err error) {
w.mu.Lock() w.mu.Lock()
defer w.mu.Unlock() defer w.mu.Unlock()
failed := []*list.Element{} for writer := range w.writers {
for e := w.writers.Front(); e != nil; e = e.Next() {
writer := e.Value.(io.Writer)
if n, err := writer.Write(p); err != nil || n != len(p) { if n, err := writer.Write(p); err != nil || n != len(p) {
// On error, evict the writer // On error, evict the writer
failed = append(failed, e) delete(w.writers, writer)
} }
} }
// We cannot remove while iterating, so it has to be done in
// a separate step
for _, e := range failed {
w.writers.Remove(e)
}
return len(p), nil return len(p), nil
} }
func (w *writeBroadcaster) Close() error { func (w *writeBroadcaster) Close() error {
w.mu.Lock() w.mu.Lock()
defer w.mu.Unlock() defer w.mu.Unlock()
for e := w.writers.Front(); e != nil; e = e.Next() { for writer := range w.writers {
writer := e.Value.(io.WriteCloser)
writer.Close() writer.Close()
} }
w.writers.Init() w.writers = make(map[io.WriteCloser]struct{})
return nil return nil
} }
func newWriteBroadcaster() *writeBroadcaster { func newWriteBroadcaster() *writeBroadcaster {
return &writeBroadcaster{writers: list.New()} return &writeBroadcaster{writers: make(map[io.WriteCloser]struct{})}
} }