github.com/Cloud-Foundations/Dominator@v0.3.4/lib/bufwriter/impl.go (about) 1 package bufwriter 2 3 import ( 4 "bufio" 5 "io" 6 "time" 7 ) 8 9 type autoFlushWriter struct { 10 writer FlushWriter 11 } 12 13 func newAutoFlushWriter(w FlushWriter) io.Writer { 14 return &autoFlushWriter{w} 15 } 16 17 func (w *autoFlushWriter) Write(p []byte) (int, error) { 18 n, err := w.writer.Write(p) 19 if err != nil { 20 return n, err 21 } 22 return n, w.writer.Flush() 23 } 24 25 func newWriter(writer io.Writer, flushDelay time.Duration) *Writer { 26 b := &Writer{flushDelay: flushDelay} 27 if bufWriter, ok := writer.(FlushWriter); ok { 28 b.flushingWriter = bufWriter 29 } else { 30 b.flushingWriter = bufio.NewWriter(writer) 31 } 32 return b 33 } 34 35 func (b *Writer) delayedFlush() { 36 time.Sleep(b.flushDelay) 37 b.flush() 38 } 39 40 func (b *Writer) flush() error { 41 b.mutex.Lock() 42 defer b.mutex.Unlock() 43 flushPending := b.flushPending 44 b.flushPending = false 45 if b.err != nil { 46 return b.err 47 } 48 if flushPending { 49 b.err = b.flushingWriter.Flush() 50 return b.err 51 } 52 return nil 53 } 54 55 func (b *Writer) lockAndScheduleFlush() { 56 b.mutex.Lock() 57 if b.flushPending { 58 return 59 } 60 b.flushPending = true 61 go b.delayedFlush() 62 } 63 64 func (b *Writer) write(p []byte) (int, error) { 65 if b.flushDelay <= 0 { 66 n, err := b.flushingWriter.Write(p) 67 if err != nil { 68 return n, err 69 } 70 return n, b.flushingWriter.Flush() 71 } 72 b.lockAndScheduleFlush() 73 defer b.mutex.Unlock() 74 if b.err != nil { 75 return 0, b.err 76 } 77 nWritten, err := b.flushingWriter.Write(p) 78 b.err = err 79 return nWritten, err 80 }