@@ -7,8 +7,12 @@ import scoverage.Platform._
7
7
object Invoker {
8
8
9
9
private val MeasurementsPrefix = " scoverage.measurements."
10
- private val threadFiles = new ThreadLocal [ThreadSafeMap [String , FileWriter ]]
11
- private val ids = ThreadSafeMap .empty[(String , Int ), Any ]
10
+ private val threadFiles = new ThreadLocal [mutable.HashMap [String , FileWriter ]]
11
+
12
+ // For each data directory we maintain a thread-safe set tracking the ids that we've already
13
+ // seen and recorded. We're using a map as a set, so we only care about its keys and can ignore
14
+ // its values.
15
+ private val dataDirToIds = ThreadSafeMap .empty[String , ThreadSafeMap [Int , Any ]]
12
16
13
17
/**
14
18
* We record that the given id has been invoked by appending its id to the coverage
@@ -31,18 +35,27 @@ object Invoker {
31
35
// times since for coverage we only care about 1 or more, (it just slows things down to
32
36
// do it more than once), anything we can do to help is good. This helps especially with code
33
37
// that is executed many times quickly, eg tight loops.
34
- if (! ids.contains(dataDir, id)) {
38
+ if (! dataDirToIds.contains(dataDir)) {
39
+ // Guard against SI-7943: "TrieMap method getOrElseUpdate is not thread-safe".
40
+ dataDirToIds.synchronized {
41
+ if (! dataDirToIds.contains(dataDir)) {
42
+ dataDirToIds(dataDir) = ThreadSafeMap .empty[Int , Any ]
43
+ }
44
+ }
45
+ }
46
+ val ids = dataDirToIds(dataDir)
47
+ if (! ids.contains(id)) {
35
48
// Each thread writes to a separate measurement file, to reduce contention
36
49
// and because file appends via FileWriter are not atomic on Windows.
37
50
var files = threadFiles.get()
38
51
if (files == null ) {
39
- files = ThreadSafeMap .empty[String , FileWriter ]
52
+ files = mutable. HashMap .empty[String , FileWriter ]
40
53
threadFiles.set(files)
41
54
}
42
55
val writer = files.getOrElseUpdate(dataDir, new FileWriter (measurementFile(dataDir), true ))
43
- writer.append(id .toString + ' \n ' ).flush()
56
+ writer.append(Integer .toString(id)).append( " \n " ).flush()
44
57
45
- ids.put((dataDir, id) , ())
58
+ ids.put(id , ())
46
59
}
47
60
}
48
61
0 commit comments