summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCaleb Bassi <calebjbassi@gmail.com>2019-01-19 20:34:19 -0800
committerCaleb Bassi <calebjbassi@gmail.com>2019-01-19 20:34:19 -0800
commit97f490be800eb3dd2092c7a1cce339272456e024 (patch)
tree97b47ba0c508f1b6d623de1b9a902e034fe7f839
parent523a190e6633194d463b78245fa12fca9e81a6c9 (diff)
Fix data race between rendering and updating
-rw-r--r--main.go57
-rw-r--r--src/termui/table.go6
-rw-r--r--src/widgets/battery.go5
-rw-r--r--src/widgets/cpu.go5
-rw-r--r--src/widgets/disk.go5
-rw-r--r--src/widgets/mem.go5
-rw-r--r--src/widgets/net.go5
-rw-r--r--src/widgets/proc.go7
-rw-r--r--src/widgets/temp.go5
9 files changed, 61 insertions, 39 deletions
diff --git a/main.go b/main.go
index 6dbac9d..dcff042 100644
--- a/main.go
+++ b/main.go
@@ -10,6 +10,7 @@ import (
"path/filepath"
"sort"
"strconv"
+ "sync"
"syscall"
"time"
@@ -46,6 +47,8 @@ var (
battery = false
statusbar = false
+ renderLock sync.RWMutex
+
cpu *w.CPU
batt *w.Batt
mem *w.Mem
@@ -257,20 +260,26 @@ func widgetColors() {
}
func initWidgets() {
- cpu = w.NewCPU(updateInterval, graphHorizontalScale, averageLoad, percpuLoad)
- mem = w.NewMem(updateInterval, graphHorizontalScale)
- proc = w.NewProc()
+ cpu = w.NewCPU(&renderLock, updateInterval, graphHorizontalScale, averageLoad, percpuLoad)
+ mem = w.NewMem(&renderLock, updateInterval, graphHorizontalScale)
+ proc = w.NewProc(&renderLock)
help = w.NewHelpMenu()
if !minimalMode {
if battery {
- batt = w.NewBatt(graphHorizontalScale)
+ batt = w.NewBatt(&renderLock, graphHorizontalScale)
}
- net = w.NewNet()
- disk = w.NewDisk()
- temp = w.NewTemp(fahrenheit)
+ net = w.NewNet(&renderLock)
+ disk = w.NewDisk(&renderLock)
+ temp = w.NewTemp(&renderLock, fahrenheit)
}
}
+func render(drawable ...ui.Drawable) {
+ renderLock.Lock()
+ ui.Render(drawable...)
+ renderLock.Unlock()
+}
+
func eventLoop() {
drawTicker := time.NewTicker(updateInterval).C
@@ -288,7 +297,7 @@ func eventLoop() {
return
case <-drawTicker:
if !helpVisible {
- ui.Render(grid)
+ render(grid)
}
case e := <-uiEvents:
switch e.ID {
@@ -310,68 +319,68 @@ func eventLoop() {
ui.Render(help)
case "<Escape>":
helpVisible = false
- ui.Render(grid)
+ render(grid)
case "<Resize>":
ui.Render(help)
}
} else {
switch e.ID {
case "?":
- ui.Render(grid)
+ render(grid)
case "h":
graphHorizontalScale += graphHorizontalScaleDelta
cpu.HorizontalScale = graphHorizontalScale
mem.HorizontalScale = graphHorizontalScale
- ui.Render(cpu, mem)
+ render(cpu, mem)
case "l":
if graphHorizontalScale > graphHorizontalScaleDelta {
graphHorizontalScale -= graphHorizontalScaleDelta
cpu.HorizontalScale = graphHorizontalScale
mem.HorizontalScale = graphHorizontalScale
- ui.Render(cpu, mem)
+ render(cpu, mem)
}
case "<Resize>":
- ui.Render(grid)
+ render(grid)
case "<MouseLeft>":
payload := e.Payload.(ui.Mouse)
proc.Click(payload.X, payload.Y)
- ui.Render(proc)
+ render(proc)
case "k", "<Up>", "<MouseWheelUp>":
proc.Up()
- ui.Render(proc)
+ render(proc)
case "j", "<Down>", "<MouseWheelDown>":
proc.Down()
- ui.Render(proc)
+ render(proc)
case "g", "<Home>":
if previousKey == "g" {
proc.Top()
- ui.Render(proc)
+ render(proc)
}
case "G", "<End>":
proc.Bottom()
- ui.Render(proc)
+ render(proc)
case "<C-d>":
proc.HalfPageDown()
- ui.Render(proc)
+ render(proc)
case "<C-u>":
proc.HalfPageUp()
- ui.Render(proc)
+ render(proc)
case "<C-f>":
proc.PageDown()
- ui.Render(proc)
+ render(proc)
case "<C-b>":
proc.PageUp()
- ui.Render(proc)
+ render(proc)
case "d":
if previousKey == "d" {
proc.Kill()
}
case "<Tab>":
proc.Tab()
- ui.Render(proc)
+ render(proc)
case "m", "c", "p":
proc.ChangeSort(e)
- ui.Render(proc)
+ render(proc)
}
if previousKey == e.ID {
diff --git a/src/termui/table.go b/src/termui/table.go
index 76e87f5..83d4849 100644
--- a/src/termui/table.go
+++ b/src/termui/table.go
@@ -3,7 +3,6 @@ package termui
import (
"image"
"strings"
- "sync"
. "github.com/gizak/termui"
)
@@ -12,8 +11,6 @@ import (
type Table struct {
*Block
- sync.Mutex
-
Header []string
Rows [][]string
@@ -51,8 +48,6 @@ func (self *Table) ColResize() {
}
func (self *Table) Draw(buf *Buffer) {
- self.Lock()
-
self.Block.Draw(buf)
self.ColResizer()
@@ -128,7 +123,6 @@ func (self *Table) Draw(buf *Buffer) {
)
}
}
- self.Unlock()
}
/////////////////////////////////////////////////////////////////////////////////
diff --git a/src/widgets/battery.go b/src/widgets/battery.go
index 3f211a8..77a5c03 100644
--- a/src/widgets/battery.go
+++ b/src/widgets/battery.go
@@ -5,6 +5,7 @@ import (
"log"
"math"
"strconv"
+ "sync"
"time"
ui "github.com/cjbassi/gotop/src/termui"
@@ -17,7 +18,7 @@ type Batt struct {
interval time.Duration
}
-func NewBatt(horizontalScale int) *Batt {
+func NewBatt(renderLock *sync.RWMutex, horizontalScale int) *Batt {
batts, err := battery.GetAll()
self := &Batt{
LineGraph: ui.NewLineGraph(),
@@ -39,7 +40,9 @@ func NewBatt(horizontalScale int) *Batt {
go func() {
ticker := time.NewTicker(self.interval)
for range ticker.C {
+ renderLock.RLock()
self.update()
+ renderLock.RUnlock()
}
}()
diff --git a/src/widgets/cpu.go b/src/widgets/cpu.go
index 8ae44e7..4502fa8 100644
--- a/src/widgets/cpu.go
+++ b/src/widgets/cpu.go
@@ -3,6 +3,7 @@ package widgets
import (
"fmt"
"log"
+ "sync"
"time"
ui "github.com/cjbassi/gotop/src/termui"
@@ -18,7 +19,7 @@ type CPU struct {
formatString string
}
-func NewCPU(interval time.Duration, horizontalScale int, average bool, percpu bool) *CPU {
+func NewCPU(renderLock *sync.RWMutex, interval time.Duration, horizontalScale int, average bool, percpu bool) *CPU {
count, err := psCPU.Counts(false)
if err != nil {
log.Printf("failed to get CPU count from gopsutil: %v", err)
@@ -62,7 +63,9 @@ func NewCPU(interval time.Duration, horizontalScale int, average bool, percpu bo
go func() {
ticker := time.NewTicker(self.interval)
for range ticker.C {
+ renderLock.RLock()
self.update()
+ renderLock.RUnlock()
}
}()
diff --git a/src/widgets/disk.go b/src/widgets/disk.go
index fe2315b..f7392df 100644
--- a/src/widgets/disk.go
+++ b/src/widgets/disk.go
@@ -5,6 +5,7 @@ import (
"log"
"sort"
"strings"
+ "sync"
"time"
ui "github.com/cjbassi/gotop/src/termui"
@@ -29,7 +30,7 @@ type Disk struct {
Partitions map[string]*Partition
}
-func NewDisk() *Disk {
+func NewDisk(renderLock *sync.RWMutex) *Disk {
self := &Disk{
Table: ui.NewTable(),
interval: time.Second,
@@ -45,7 +46,9 @@ func NewDisk() *Disk {
go func() {
ticker := time.NewTicker(self.interval)
for range ticker.C {
+ renderLock.RLock()
self.update()
+ renderLock.RUnlock()
}
}()
diff --git a/src/widgets/mem.go b/src/widgets/mem.go
index 906da9b..4c5a3a5 100644
--- a/src/widgets/mem.go
+++ b/src/widgets/mem.go
@@ -3,6 +3,7 @@ package widgets
import (
"fmt"
"log"
+ "sync"
"time"
ui "github.com/cjbassi/gotop/src/termui"
@@ -15,7 +16,7 @@ type Mem struct {
interval time.Duration
}
-func NewMem(interval time.Duration, horizontalScale int) *Mem {
+func NewMem(renderLock *sync.RWMutex, interval time.Duration, horizontalScale int) *Mem {
self := &Mem{
LineGraph: ui.NewLineGraph(),
interval: interval,
@@ -30,7 +31,9 @@ func NewMem(interval time.Duration, horizontalScale int) *Mem {
go func() {
ticker := time.NewTicker(self.interval)
for range ticker.C {
+ renderLock.RLock()
self.update()
+ renderLock.RUnlock()
}
}()
diff --git a/src/widgets/net.go b/src/widgets/net.go
index 1a3c263..740e044 100644
--- a/src/widgets/net.go
+++ b/src/widgets/net.go
@@ -3,6 +3,7 @@ package widgets
import (
"fmt"
"log"
+ "sync"
"time"
ui "github.com/cjbassi/gotop/src/termui"
@@ -18,7 +19,7 @@ type Net struct {
prevSentTotal uint64
}
-func NewNet() *Net {
+func NewNet(renderLock *sync.RWMutex) *Net {
recv := ui.NewSparkline()
recv.Data = []int{0}
@@ -37,7 +38,9 @@ func NewNet() *Net {
go func() {
ticker := time.NewTicker(self.interval)
for range ticker.C {
+ renderLock.RLock()
self.update()
+ renderLock.RUnlock()
}
}()
diff --git a/src/widgets/proc.go b/src/widgets/proc.go
index f3dc441..69fd199 100644
--- a/src/widgets/proc.go
+++ b/src/widgets/proc.go
@@ -6,6 +6,7 @@ import (
"os/exec"
"sort"
"strconv"
+ "sync"
"time"
ui "github.com/cjbassi/gotop/src/termui"
@@ -38,7 +39,7 @@ type Proc struct {
group bool
}
-func NewProc() *Proc {
+func NewProc(renderLock *sync.RWMutex) *Proc {
cpuCount, err := psCPU.Counts(false)
if err != nil {
log.Printf("failed to get CPU count from gopsutil: %v", err)
@@ -66,9 +67,9 @@ func NewProc() *Proc {
go func() {
ticker := time.NewTicker(self.interval)
for range ticker.C {
- self.Lock()
+ renderLock.RLock()
self.update()
- self.Unlock()
+ renderLock.RUnlock()
}
}()
diff --git a/src/widgets/temp.go b/src/widgets/temp.go
index 9c1b2e9..76ef243 100644
--- a/src/widgets/temp.go
+++ b/src/widgets/temp.go
@@ -7,6 +7,7 @@ import (
"fmt"
"image"
"sort"
+ "sync"
"time"
ui "github.com/gizak/termui"
@@ -22,7 +23,7 @@ type Temp struct {
Fahrenheit bool
}
-func NewTemp(fahrenheit bool) *Temp {
+func NewTemp(renderLock *sync.RWMutex, fahrenheit bool) *Temp {
self := &Temp{
Block: ui.NewBlock(),
interval: time.Second * 5,
@@ -41,7 +42,9 @@ func NewTemp(fahrenheit bool) *Temp {
go func() {
ticker := time.NewTicker(self.interval)
for range ticker.C {
+ renderLock.RLock()
self.update()
+ renderLock.RUnlock()
}
}()