github.com/jmigpin/editor@v1.6.0/util/iout/autobufwriter.go (about) 1 package iout 2 3 import ( 4 "bufio" 5 "io" 6 "sync" 7 "time" 8 ) 9 10 //godebug:annotatefile 11 12 // small amounts of output need to be flushed (not filling the buffer) 13 const abwUpdatesPerSecond = 10 14 15 // Flushes after x time if the buffer doesn't get filled. Safe to use concurrently. 16 type AutoBufWriter struct { 17 w io.Writer 18 mu struct { 19 sync.Mutex 20 buf *bufio.Writer 21 timer *time.Timer 22 } 23 } 24 25 func NewAutoBufWriter(w io.Writer, size int) *AutoBufWriter { 26 abw := &AutoBufWriter{w: w} 27 abw.mu.buf = bufio.NewWriterSize(abw.w, size) 28 return abw 29 } 30 31 // Implements io.Closer 32 func (w *AutoBufWriter) Close() error { 33 w.mu.Lock() 34 defer w.mu.Unlock() 35 w.clearTimer() 36 w.mu.buf.Flush() 37 return nil 38 } 39 40 // Implements io.Writer 41 func (w *AutoBufWriter) Write(p []byte) (int, error) { 42 w.mu.Lock() 43 defer w.mu.Unlock() 44 n, err := w.mu.buf.Write(p) 45 w.autoFlush() 46 return n, err 47 } 48 49 //---------- 50 51 func (w *AutoBufWriter) autoFlush() { 52 if w.mu.buf.Buffered() == 0 { 53 return 54 } 55 if w.mu.timer == nil { 56 t := time.Second / abwUpdatesPerSecond 57 w.mu.timer = time.AfterFunc(t, w.flushTime) 58 } 59 } 60 func (w *AutoBufWriter) flushTime() { 61 w.mu.Lock() 62 defer w.mu.Unlock() 63 w.mu.buf.Flush() 64 w.clearTimer() 65 } 66 67 func (w *AutoBufWriter) clearTimer() { 68 if w.mu.timer != nil { 69 w.mu.timer.Stop() 70 w.mu.timer = nil 71 } 72 }