Skip to content

Commit e1b63ee

Browse files
authored
Merge pull request #291 from sharwell/interlocked-record
Record hits without thread local variables
2 parents d4c51c3 + 6ae1a89 commit e1b63ee

File tree

1 file changed

+8
-43
lines changed

1 file changed

+8
-43
lines changed

src/coverlet.template/ModuleTrackerTemplate.cs

+8-43
Original file line numberDiff line numberDiff line change
@@ -20,68 +20,33 @@ public static class ModuleTrackerTemplate
2020
public static string HitsFilePath;
2121
public static int[] HitsArray;
2222

23-
// Special case when instrumenting CoreLib, the thread static below prevents infinite loop in CoreLib
23+
// Special case when instrumenting CoreLib, the static below prevents infinite loop in CoreLib
2424
// while allowing the tracker template to call any of its types and functions.
25-
[ThreadStatic]
26-
private static bool t_isTracking;
27-
28-
[ThreadStatic]
29-
private static int[] t_threadHits;
30-
31-
private static List<int[]> _threads;
25+
private static bool s_isTracking;
3226

3327
static ModuleTrackerTemplate()
3428
{
35-
t_isTracking = true;
36-
_threads = new List<int[]>(2 * Environment.ProcessorCount);
37-
29+
s_isTracking = true;
3830
AppDomain.CurrentDomain.ProcessExit += new EventHandler(UnloadModule);
3931
AppDomain.CurrentDomain.DomainUnload += new EventHandler(UnloadModule);
40-
t_isTracking = false;
32+
s_isTracking = false;
33+
4134
// At the end of the instrumentation of a module, the instrumenter needs to add code here
4235
// to initialize the static fields according to the values derived from the instrumentation of
4336
// the module.
4437
}
4538

4639
public static void RecordHit(int hitLocationIndex)
4740
{
48-
if (t_isTracking)
41+
if (s_isTracking)
4942
return;
5043

51-
if (t_threadHits == null)
52-
{
53-
t_isTracking = true;
54-
lock (_threads)
55-
{
56-
if (t_threadHits == null)
57-
{
58-
t_threadHits = new int[HitsArray.Length];
59-
_threads.Add(t_threadHits);
60-
}
61-
}
62-
t_isTracking = false;
63-
}
64-
65-
++t_threadHits[hitLocationIndex];
44+
Interlocked.Increment(ref HitsArray[hitLocationIndex]);
6645
}
6746

6847
public static void UnloadModule(object sender, EventArgs e)
6948
{
70-
t_isTracking = true;
71-
72-
// Update the global hits array from data from all the threads
73-
lock (_threads)
74-
{
75-
foreach (var threadHits in _threads)
76-
{
77-
for (int i = 0; i < HitsArray.Length; ++i)
78-
HitsArray[i] += threadHits[i];
79-
}
80-
81-
// Prevent any double counting scenario, i.e.: UnloadModule called twice (not sure if this can happen in practice ...)
82-
// Only an issue if DomainUnload and ProcessExit can both happens, perhaps can be removed...
83-
_threads.Clear();
84-
}
49+
s_isTracking = true;
8550

8651
// The same module can be unloaded multiple times in the same process via different app domains.
8752
// Use a global mutex to ensure no concurrent access.

0 commit comments

Comments
 (0)