diff --git a/BitFaster.Caching.Benchmarks/BitFaster.Caching.Benchmarks.csproj b/BitFaster.Caching.Benchmarks/BitFaster.Caching.Benchmarks.csproj index f61ff6a9..1e8071a5 100644 --- a/BitFaster.Caching.Benchmarks/BitFaster.Caching.Benchmarks.csproj +++ b/BitFaster.Caching.Benchmarks/BitFaster.Caching.Benchmarks.csproj @@ -3,6 +3,7 @@ Exe net48;net6.0;net8.0 + 10.0 True true diff --git a/BitFaster.Caching/Lru/AfterAccessPolicy.cs b/BitFaster.Caching/Lru/AfterAccessPolicy.cs index 98c6c5dd..f40b0a73 100644 --- a/BitFaster.Caching/Lru/AfterAccessPolicy.cs +++ b/BitFaster.Caching/Lru/AfterAccessPolicy.cs @@ -40,7 +40,7 @@ public LongTickCountLruItem CreateItem(K key, V value) public void Touch(LongTickCountLruItem item) { item.TickCount = this.time.Last; - item.WasAccessed = true; + item.MarkAccessed(); } /// diff --git a/BitFaster.Caching/Lru/DiscretePolicy.cs b/BitFaster.Caching/Lru/DiscretePolicy.cs index 8e70a327..636244d9 100644 --- a/BitFaster.Caching/Lru/DiscretePolicy.cs +++ b/BitFaster.Caching/Lru/DiscretePolicy.cs @@ -35,7 +35,7 @@ public void Touch(LongTickCountLruItem item) var currentExpiry = new Duration(item.TickCount - this.time.Last); var newExpiry = expiry.GetExpireAfterRead(item.Key, item.Value, currentExpiry); item.TickCount = this.time.Last + newExpiry.raw; - item.WasAccessed = true; + item.MarkAccessed(); } /// diff --git a/BitFaster.Caching/Lru/LruItem.cs b/BitFaster.Caching/Lru/LruItem.cs index f2e865c9..77b639fe 100644 --- a/BitFaster.Caching/Lru/LruItem.cs +++ b/BitFaster.Caching/Lru/LruItem.cs @@ -14,8 +14,8 @@ public class LruItem { private V data; - private volatile bool wasAccessed; - private volatile bool wasRemoved; + private bool wasAccessed; + private bool wasRemoved; // only used when V is a non-atomic value type to prevent torn reads private int sequence; @@ -72,8 +72,8 @@ public V Value /// public bool WasAccessed { - get => this.wasAccessed; - set => this.wasAccessed = value; + get => Volatile.Read(ref this.wasAccessed); + set => Volatile.Write(ref this.wasAccessed, value); } /// @@ -81,8 +81,19 @@ public bool WasAccessed /// public bool WasRemoved { - get => this.wasRemoved; - set => this.wasRemoved = value; + get => Volatile.Read(ref this.wasRemoved); + set => Volatile.Write(ref this.wasRemoved, value); + } + + /// + /// Marks the item as accessed, if it was not already accessed. + /// + public void MarkAccessed() + { + if (!Volatile.Read(ref this.wasAccessed)) + { + Volatile.Write(ref this.wasAccessed, true); + } } internal V SeqLockRead() diff --git a/BitFaster.Caching/Lru/LruPolicy.cs b/BitFaster.Caching/Lru/LruPolicy.cs index cc1d93a0..12495dd9 100644 --- a/BitFaster.Caching/Lru/LruPolicy.cs +++ b/BitFaster.Caching/Lru/LruPolicy.cs @@ -23,7 +23,7 @@ public LruItem CreateItem(K key, V value) [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Touch(LruItem item) { - item.WasAccessed = true; + item.MarkAccessed(); } /// diff --git a/BitFaster.Caching/Lru/TLruLongTicksPolicy.cs b/BitFaster.Caching/Lru/TLruLongTicksPolicy.cs index fb64ca3e..41ee8355 100644 --- a/BitFaster.Caching/Lru/TLruLongTicksPolicy.cs +++ b/BitFaster.Caching/Lru/TLruLongTicksPolicy.cs @@ -38,7 +38,7 @@ public LongTickCountLruItem CreateItem(K key, V value) [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Touch(LongTickCountLruItem item) { - item.WasAccessed = true; + item.MarkAccessed(); } /// diff --git a/BitFaster.Caching/Lru/TlruDateTimePolicy.cs b/BitFaster.Caching/Lru/TlruDateTimePolicy.cs index 81e3a078..b7207a5b 100644 --- a/BitFaster.Caching/Lru/TlruDateTimePolicy.cs +++ b/BitFaster.Caching/Lru/TlruDateTimePolicy.cs @@ -35,7 +35,7 @@ public TimeStampedLruItem CreateItem(K key, V value) [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Touch(TimeStampedLruItem item) { - item.WasAccessed = true; + item.MarkAccessed(); } /// diff --git a/BitFaster.Caching/Lru/TlruTicksPolicy.cs b/BitFaster.Caching/Lru/TlruTicksPolicy.cs index 1ce6bd5a..d6bc0047 100644 --- a/BitFaster.Caching/Lru/TlruTicksPolicy.cs +++ b/BitFaster.Caching/Lru/TlruTicksPolicy.cs @@ -40,7 +40,7 @@ public TickCountLruItem CreateItem(K key, V value) [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Touch(TickCountLruItem item) { - item.WasAccessed = true; + item.MarkAccessed(); } ///