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 "": helpVisible = false - ui.Render(grid) + render(grid) case "": 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 "": - ui.Render(grid) + render(grid) case "": payload := e.Payload.(ui.Mouse) proc.Click(payload.X, payload.Y) - ui.Render(proc) + render(proc) case "k", "", "": proc.Up() - ui.Render(proc) + render(proc) case "j", "", "": proc.Down() - ui.Render(proc) + render(proc) case "g", "": if previousKey == "g" { proc.Top() - ui.Render(proc) + render(proc) } case "G", "": proc.Bottom() - ui.Render(proc) + render(proc) case "": proc.HalfPageDown() - ui.Render(proc) + render(proc) case "": proc.HalfPageUp() - ui.Render(proc) + render(proc) case "": proc.PageDown() - ui.Render(proc) + render(proc) case "": proc.PageUp() - ui.Render(proc) + render(proc) case "d": if previousKey == "d" { proc.Kill() } case "": 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() } }()