Parcourir la source

Ensure SrcFile is goroutine-safe (as it may be shared between multiple runtimes)

Dmitry Panov il y a 6 ans
Parent
commit
084dd324c7
2 fichiers modifiés avec 21 ajouts et 2 suppressions
  1. 10 2
      srcfile.go
  2. 11 0
      srcfile_test.go

+ 10 - 2
srcfile.go

@@ -5,6 +5,7 @@ import (
 	"github.com/go-sourcemap/sourcemap"
 	"sort"
 	"strings"
+	"sync"
 )
 
 type Position struct {
@@ -16,6 +17,7 @@ type SrcFile struct {
 	src  string
 
 	lineOffsets       []int
+	lineOffsetsLock   sync.Mutex
 	lastScannedOffset int
 	sourceMap         *sourcemap.Consumer
 }
@@ -30,15 +32,21 @@ func NewSrcFile(name, src string, sourceMap *sourcemap.Consumer) *SrcFile {
 
 func (f *SrcFile) Position(offset int) Position {
 	var line int
+	var lineOffsets []int
+	f.lineOffsetsLock.Lock()
 	if offset > f.lastScannedOffset {
 		line = f.scanTo(offset)
+		lineOffsets = f.lineOffsets
+		f.lineOffsetsLock.Unlock()
 	} else {
-		line = sort.Search(len(f.lineOffsets), func(x int) bool { return f.lineOffsets[x] > offset }) - 1
+		lineOffsets = f.lineOffsets
+		f.lineOffsetsLock.Unlock()
+		line = sort.Search(len(lineOffsets), func(x int) bool { return lineOffsets[x] > offset }) - 1
 	}
 
 	var lineStart int
 	if line >= 0 {
-		lineStart = f.lineOffsets[line]
+		lineStart = lineOffsets[line]
 	}
 
 	row := line + 2

+ 11 - 0
srcfile_test.go

@@ -32,3 +32,14 @@ line3`
 		}
 	}
 }
+
+func TestSrcFileConcurrency(t *testing.T) {
+	const SRC = `line1
+line2
+line3`
+	f := NewSrcFile("", SRC, nil)
+	go func() {
+		f.Position(12)
+	}()
+	f.Position(2)
+}