diff --git a/cs/src/core/Allocator/AllocatorBase.cs b/cs/src/core/Allocator/AllocatorBase.cs
index 48f53fb39..557cddea3 100644
--- a/cs/src/core/Allocator/AllocatorBase.cs
+++ b/cs/src/core/Allocator/AllocatorBase.cs
@@ -870,7 +870,7 @@ public void ShiftReadOnlyToTail(out long tailAddress)
tailAddress = GetTailAddress();
long localTailAddress = tailAddress;
long currentReadOnlyOffset = ReadOnlyAddress;
- if (MonotonicUpdate(ref ReadOnlyAddress, tailAddress, out long oldReadOnlyOffset))
+ if (Utility.MonotonicUpdate(ref ReadOnlyAddress, tailAddress, out long oldReadOnlyOffset))
{
epoch.BumpCurrentEpoch(() => OnPagesMarkedReadOnly(localTailAddress, false));
}
@@ -882,7 +882,7 @@ public void ShiftReadOnlyToTail(out long tailAddress)
///
public bool ShiftReadOnlyAddress(long newReadOnlyAddress)
{
- if (MonotonicUpdate(ref ReadOnlyAddress, newReadOnlyAddress, out long oldReadOnlyOffset))
+ if (Utility.MonotonicUpdate(ref ReadOnlyAddress, newReadOnlyAddress, out long oldReadOnlyOffset))
{
epoch.BumpCurrentEpoch(() => OnPagesMarkedReadOnly(newReadOnlyAddress, false));
return true;
@@ -897,19 +897,19 @@ public bool ShiftReadOnlyAddress(long newReadOnlyAddress)
public void ShiftBeginAddress(long newBeginAddress)
{
// First update the begin address
- MonotonicUpdate(ref BeginAddress, newBeginAddress, out long oldBeginAddress);
+ Utility.MonotonicUpdate(ref BeginAddress, newBeginAddress, out long oldBeginAddress);
// Then the head address
- var h = MonotonicUpdate(ref HeadAddress, newBeginAddress, out long old);
+ var h = Utility.MonotonicUpdate(ref HeadAddress, newBeginAddress, out long old);
// Finally the read-only address
- var r = MonotonicUpdate(ref ReadOnlyAddress, newBeginAddress, out old);
+ var r = Utility.MonotonicUpdate(ref ReadOnlyAddress, newBeginAddress, out old);
// Clean up until begin address
epoch.BumpCurrentEpoch(() =>
{
if (r)
{
- MonotonicUpdate(ref SafeReadOnlyAddress, newBeginAddress, out long _old);
- MonotonicUpdate(ref FlushedUntilAddress, newBeginAddress, out _old);
+ Utility.MonotonicUpdate(ref SafeReadOnlyAddress, newBeginAddress, out long _old);
+ Utility.MonotonicUpdate(ref FlushedUntilAddress, newBeginAddress, out _old);
}
if (h) OnPagesClosed(newBeginAddress);
@@ -935,7 +935,7 @@ protected virtual void DeleteAddressRange(long fromAddress, long toAddress)
///
public void OnPagesMarkedReadOnly(long newSafeReadOnlyAddress, bool waitForPendingFlushComplete = false)
{
- if (MonotonicUpdate(ref SafeReadOnlyAddress, newSafeReadOnlyAddress, out long oldSafeReadOnlyAddress))
+ if (Utility.MonotonicUpdate(ref SafeReadOnlyAddress, newSafeReadOnlyAddress, out long oldSafeReadOnlyAddress))
{
Debug.WriteLine("SafeReadOnly shifted from {0:X} to {1:X}", oldSafeReadOnlyAddress, newSafeReadOnlyAddress);
long startPage = oldSafeReadOnlyAddress >> LogPageSizeBits;
@@ -964,7 +964,7 @@ public void OnPagesMarkedReadOnly(long newSafeReadOnlyAddress, bool waitForPendi
///
public void OnPagesClosed(long newSafeHeadAddress)
{
- if (MonotonicUpdate(ref SafeHeadAddress, newSafeHeadAddress, out long oldSafeHeadAddress))
+ if (Utility.MonotonicUpdate(ref SafeHeadAddress, newSafeHeadAddress, out long oldSafeHeadAddress))
{
Debug.WriteLine("SafeHeadOffset shifted from {0:X} to {1:X}", oldSafeHeadAddress, newSafeHeadAddress);
@@ -1020,7 +1020,7 @@ private void PageAlignedShiftReadOnlyAddress(long currentTailAddress)
long currentReadOnlyAddress = ReadOnlyAddress;
long pageAlignedTailAddress = currentTailAddress & ~PageSizeMask;
long desiredReadOnlyAddress = (pageAlignedTailAddress - ReadOnlyLagAddress);
- if (MonotonicUpdate(ref ReadOnlyAddress, desiredReadOnlyAddress, out long oldReadOnlyAddress))
+ if (Utility.MonotonicUpdate(ref ReadOnlyAddress, desiredReadOnlyAddress, out long oldReadOnlyAddress))
{
Debug.WriteLine("Allocate: Moving read-only offset from {0:X} to {1:X}", oldReadOnlyAddress, desiredReadOnlyAddress);
epoch.BumpCurrentEpoch(() => OnPagesMarkedReadOnly(desiredReadOnlyAddress));
@@ -1050,7 +1050,7 @@ private void PageAlignedShiftHeadAddress(long currentTailAddress)
if (ReadCache && (newHeadAddress > HeadAddress))
EvictCallback(HeadAddress, newHeadAddress);
- if (MonotonicUpdate(ref HeadAddress, newHeadAddress, out long oldHeadAddress))
+ if (Utility.MonotonicUpdate(ref HeadAddress, newHeadAddress, out long oldHeadAddress))
{
Debug.WriteLine("Allocate: Moving head offset from {0:X} to {1:X}", oldHeadAddress, newHeadAddress);
epoch.BumpCurrentEpoch(() => OnPagesClosed(newHeadAddress));
@@ -1075,7 +1075,7 @@ public long ShiftHeadAddress(long desiredHeadAddress)
if (ReadCache && (newHeadAddress > HeadAddress))
EvictCallback(HeadAddress, newHeadAddress);
- if (MonotonicUpdate(ref HeadAddress, newHeadAddress, out long oldHeadAddress))
+ if (Utility.MonotonicUpdate(ref HeadAddress, newHeadAddress, out long oldHeadAddress))
{
Debug.WriteLine("Allocate: Moving head offset from {0:X} to {1:X}", oldHeadAddress, newHeadAddress);
epoch.BumpCurrentEpoch(() => OnPagesClosed(newHeadAddress));
@@ -1104,35 +1104,10 @@ protected void ShiftFlushedUntilAddress()
if (update)
{
- MonotonicUpdate(ref FlushedUntilAddress, currentFlushedUntilAddress, out long oldFlushedUntilAddress);
+ Utility.MonotonicUpdate(ref FlushedUntilAddress, currentFlushedUntilAddress, out long oldFlushedUntilAddress);
}
}
-
-
- ///
- /// Used by several functions to update the variable to newValue. Ignores if newValue is smaller or
- /// than the current value.
- ///
- ///
- ///
- ///
- ///
- private bool MonotonicUpdate(ref long variable, long newValue, out long oldValue)
- {
- oldValue = variable;
- while (oldValue < newValue)
- {
- var foundValue = Interlocked.CompareExchange(ref variable, newValue, oldValue);
- if (foundValue == oldValue)
- {
- return true;
- }
- oldValue = foundValue;
- }
- return false;
- }
-
///
/// Reset for recovery
///
diff --git a/cs/src/core/Utilities/Utility.cs b/cs/src/core/Utilities/Utility.cs
index 57ab7168f..375b20cfc 100644
--- a/cs/src/core/Utilities/Utility.cs
+++ b/cs/src/core/Utilities/Utility.cs
@@ -223,5 +223,39 @@ internal static int Murmur3(int h)
a ^= a >> 16;
return (int)a;
}
+
+ ///
+ /// Updates the variable to newValue only if the current value is smaller than the new value.
+ ///
+ /// The variable to possibly replace
+ /// The value that replaces the variable if successful
+ /// The orignal value in the variable
+ /// if oldValue less than newValue
+ public static bool MonotonicUpdate(ref long variable, long newValue, out long oldValue)
+ {
+ do
+ {
+ oldValue = variable;
+ if (oldValue > newValue) return false;
+ } while (Interlocked.CompareExchange(ref variable, newValue, oldValue) != oldValue);
+ return true;
+ }
+ ///
+ /// Updates the variable to newValue only if the current value is smaller than the new value.
+ ///
+ /// The variable to possibly replace
+ /// The value that replaces the variable if successful
+ /// The orignal value in the variable
+ /// if oldValue less than newValue
+ public static bool MonotonicUpdate(ref int variable, int newValue, out int oldValue)
+ {
+ do
+ {
+ oldValue = variable;
+ if (oldValue > newValue) return false;
+ } while (Interlocked.CompareExchange(ref variable, newValue, oldValue) != oldValue);
+ return true;
+ }
+
}
}