diff --git a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/PersistentStorage/DirectorySizeTracker.cs b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/PersistentStorage/DirectorySizeTracker.cs
index 26c607abb7..2bbc352817 100644
--- a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/PersistentStorage/DirectorySizeTracker.cs
+++ b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/PersistentStorage/DirectorySizeTracker.cs
@@ -36,14 +36,14 @@ public DirectorySizeTracker(long maxSizeInBytes, string path)
/// True if space is available else false.
public bool IsSpaceAvailable(out long currentSizeInBytes)
{
- currentSizeInBytes = Volatile.Read(ref this.directoryCurrentSizeInBytes);
+ currentSizeInBytes = Interlocked.Read(ref this.directoryCurrentSizeInBytes);
return currentSizeInBytes < this.maxSizeInBytes;
}
public void RecountCurrentSize()
{
var size = CalculateFolderSize(this.path);
- Volatile.Write(ref this.directoryCurrentSizeInBytes, size);
+ Interlocked.Exchange(ref this.directoryCurrentSizeInBytes, size);
}
internal static long CalculateFolderSize(string path)
diff --git a/src/OpenTelemetry/Internal/InterlockedHelper.cs b/src/OpenTelemetry/Internal/InterlockedHelper.cs
index 596c7eb89c..98639d234a 100644
--- a/src/OpenTelemetry/Internal/InterlockedHelper.cs
+++ b/src/OpenTelemetry/Internal/InterlockedHelper.cs
@@ -10,9 +10,30 @@ internal static class InterlockedHelper
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void Add(ref double location, double value)
{
+ // Note: Not calling InterlockedHelper.Read here on purpose because it
+ // is too expensive for fast/happy-path. If the first attempt fails
+ // we'll end up in an Interlocked.CompareExchange loop anyway.
double currentValue = Volatile.Read(ref location);
+
+ var returnedValue = Interlocked.CompareExchange(ref location, currentValue + value, currentValue);
+ if (returnedValue != currentValue)
+ {
+ AddRare(ref location, value, returnedValue);
+ }
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static double Read(ref double location)
+ => Interlocked.CompareExchange(ref location, double.NaN, double.NaN);
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ private static void AddRare(ref double location, double value, double currentValue)
+ {
+ var sw = default(SpinWait);
while (true)
{
+ sw.SpinOnce();
+
var returnedValue = Interlocked.CompareExchange(ref location, currentValue + value, currentValue);
if (returnedValue == currentValue)
{
@@ -22,8 +43,4 @@ public static void Add(ref double location, double value)
currentValue = returnedValue;
}
}
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static double Read(ref double location)
- => Interlocked.CompareExchange(ref location, 0, 0);
}
diff --git a/src/OpenTelemetry/Metrics/Exemplar/Exemplar.cs b/src/OpenTelemetry/Metrics/Exemplar/Exemplar.cs
index 6f32e43d1d..d1801afdd3 100644
--- a/src/OpenTelemetry/Metrics/Exemplar/Exemplar.cs
+++ b/src/OpenTelemetry/Metrics/Exemplar/Exemplar.cs
@@ -135,7 +135,7 @@ internal void Update(in ExemplarMeasurement measurement)
this.StoreRawTags(measurement.Tags);
}
- Volatile.Write(ref this.isCriticalSectionOccupied, 0);
+ Interlocked.Exchange(ref this.isCriticalSectionOccupied, 0);
}
internal void Reset()
@@ -168,7 +168,7 @@ internal void Collect(ref Exemplar destination, bool reset)
destination.Reset();
}
- Volatile.Write(ref this.isCriticalSectionOccupied, 0);
+ Interlocked.Exchange(ref this.isCriticalSectionOccupied, 0);
}
internal readonly void Copy(ref Exemplar destination)
diff --git a/src/OpenTelemetry/Metrics/MetricPoint/MetricPoint.cs b/src/OpenTelemetry/Metrics/MetricPoint/MetricPoint.cs
index eea5c83bfa..8c0ad5951f 100644
--- a/src/OpenTelemetry/Metrics/MetricPoint/MetricPoint.cs
+++ b/src/OpenTelemetry/Metrics/MetricPoint/MetricPoint.cs
@@ -394,7 +394,7 @@ internal void Update(long number)
case AggregationType.LongSumIncomingCumulative:
case AggregationType.LongGauge:
{
- Volatile.Write(ref this.runningValue.AsLong, number);
+ Interlocked.Exchange(ref this.runningValue.AsLong, number);
break;
}
@@ -451,7 +451,7 @@ internal void UpdateWithExemplar(long number, ReadOnlySpan