summaryrefslogtreecommitdiff
path: root/go/src/lib/statusline/stopwatch.go
diff options
context:
space:
mode:
Diffstat (limited to 'go/src/lib/statusline/stopwatch.go')
-rw-r--r--go/src/lib/statusline/stopwatch.go71
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
+}