diff options
Diffstat (limited to 'go/src/lib/statusline/stopwatch.go')
-rw-r--r-- | go/src/lib/statusline/stopwatch.go | 71 |
1 files changed, 71 insertions, 0 deletions
diff --git a/go/src/lib/statusline/stopwatch.go b/go/src/lib/statusline/stopwatch.go new file mode 100644 index 0000000..4e3bb5b --- /dev/null +++ b/go/src/lib/statusline/stopwatch.go @@ -0,0 +1,71 @@ +package statusline + +import ( + "fmt" + "sync" + "time" +) + +type stopWatch struct { + inner StatusLine + precision time.Duration + + start time.Time + line string + + once sync.Once + + lines chan string + end1 chan bool + end2 chan struct{} +} + +func StopWatch(sl StatusLine, precision time.Duration) StatusLine { + return &stopWatch{ + inner: sl, + precision: precision, + lines: make(chan string), + end1: make(chan bool), + end2: make(chan struct{}), + } +} + +func (sw *stopWatch) startWorker() { + go func() { + sw.start = time.Now() + ticker := time.NewTicker(sw.precision) + for { + select { + case <-ticker.C: + sw.tick() + case sw.line = <-sw.lines: + sw.tick() + case keep := <-sw.end1: + sw.tick() + sw.inner.End(keep) + ticker.Stop() + sw.end2 <- struct{}{} + close(sw.end2) + return + } + } + }() +} + +func (sw *stopWatch) tick() { + d := time.Now().Sub(sw.start).Round(sw.precision) + sw.inner.Put(fmt.Sprintf("[ %v ] %s", d, sw.line)) +} + +func (sl *stopWatch) Put(line string) { + sl.once.Do(sl.startWorker) + sl.lines <- line +} + +func (sl *stopWatch) End(keep bool) { + sl.once.Do(sl.startWorker) + sl.end1 <- keep + close(sl.lines) + close(sl.end1) + <-sl.end2 +} |