From b6dcbfa846c2a618a04969ccbdf2dd1a1af15601 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6ran=20Karl?= <3951388+JoeKar@users.noreply.github.com> Date: Thu, 4 Apr 2024 21:55:50 +0200 Subject: [PATCH] highlighter: Fix race between the async highlighter and the main routine This is achieved by the usage of the new `LineArray` locking machanism, which prevents the interruption in the moment of modifications like insertion or removal of lines. Co-authored-by: Dmytro Maluka --- pkg/highlight/highlighter.go | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/pkg/highlight/highlighter.go b/pkg/highlight/highlighter.go index 7552671c..547e606d 100644 --- a/pkg/highlight/highlighter.go +++ b/pkg/highlight/highlighter.go @@ -77,6 +77,8 @@ type LineStates interface { State(lineN int) State SetState(lineN int, s State) SetMatch(lineN int, m LineMatch) + Lock() + Unlock() } // A Highlighter contains the information needed to highlight a string @@ -303,7 +305,13 @@ func (h *Highlighter) HighlightString(input string) []LineMatch { // HighlightStates correctly sets all states for the buffer func (h *Highlighter) HighlightStates(input LineStates) { - for i := 0; i < input.LinesNum(); i++ { + for i := 0; ; i++ { + input.Lock() + if i >= input.LinesNum() { + input.Unlock() + break + } + line := input.LineBytes(i) // highlights := make(LineMatch) @@ -316,6 +324,7 @@ func (h *Highlighter) HighlightStates(input LineStates) { curState := h.lastRegion input.SetState(i, curState) + input.Unlock() } } @@ -324,7 +333,9 @@ func (h *Highlighter) HighlightStates(input LineStates) { // This assumes that all the states are set correctly func (h *Highlighter) HighlightMatches(input LineStates, startline, endline int) { for i := startline; i <= endline; i++ { + input.Lock() if i >= input.LinesNum() { + input.Unlock() break } @@ -339,6 +350,7 @@ func (h *Highlighter) HighlightMatches(input LineStates, startline, endline int) } input.SetMatch(i, match) + input.Unlock() } } @@ -350,9 +362,17 @@ func (h *Highlighter) ReHighlightStates(input LineStates, startline int) int { h.lastRegion = nil if startline > 0 { + input.Lock() h.lastRegion = input.State(startline - 1) + input.Unlock() } - for i := startline; i < input.LinesNum(); i++ { + for i := startline; ; i++ { + input.Lock() + if i >= input.LinesNum() { + input.Unlock() + break + } + line := input.LineBytes(i) // highlights := make(LineMatch) @@ -366,6 +386,7 @@ func (h *Highlighter) ReHighlightStates(input LineStates, startline int) int { lastState := input.State(i) input.SetState(i, curState) + input.Unlock() if curState == lastState { return i @@ -377,6 +398,9 @@ func (h *Highlighter) ReHighlightStates(input LineStates, startline int) int { // ReHighlightLine will rehighlight the state and match for a single line func (h *Highlighter) ReHighlightLine(input LineStates, lineN int) { + input.Lock() + defer input.Unlock() + line := input.LineBytes(lineN) highlights := make(LineMatch)