@@ -10,9 +10,10 @@ internal interface INodePolicy<K, V, N>
1010 {
1111 N Create ( K key , V value ) ;
1212 bool IsExpired ( N node ) ;
13- void AdvanceTime ( ) ;
1413 void OnRead ( N node ) ;
1514 void OnWrite ( N node ) ;
15+ void AfterRead ( N node ) ;
16+ void AfterWrite ( N node ) ;
1617 void OnEvict ( N node ) ;
1718 void ExpireEntries < P > ( ref ConcurrentLfuCore < K , V , N , P > cache ) where P : struct , INodePolicy < K , V , N > ;
1819 }
@@ -33,17 +34,22 @@ public bool IsExpired(AccessOrderNode<K, V> node)
3334 }
3435
3536 [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
36- public void AdvanceTime ( )
37+ public void OnRead ( AccessOrderNode < K , V > node )
3738 {
3839 }
3940
4041 [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
41- public void OnRead ( AccessOrderNode < K , V > node )
42+ public void OnWrite ( AccessOrderNode < K , V > node )
4243 {
4344 }
4445
4546 [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
46- public void OnWrite ( AccessOrderNode < K , V > node )
47+ public void AfterRead ( AccessOrderNode < K , V > node )
48+ {
49+ }
50+
51+ [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
52+ public void AfterWrite ( AccessOrderNode < K , V > node )
4753 {
4854 }
4955
@@ -84,29 +90,33 @@ public TimeOrderNode<K, V> Create(K key, V value)
8490
8591 [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
8692 public bool IsExpired ( TimeOrderNode < K , V > node )
87- {
88- return node . TimeToExpire < Duration . SinceEpoch ( ) ;
89- }
90-
91- [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
92- public void AdvanceTime ( )
9393 {
9494 current = Duration . SinceEpoch ( ) ;
95+ return node . TimeToExpire < current ;
9596 }
9697
9798 [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
9899 public void OnRead ( TimeOrderNode < K , V > node )
99100 {
100- var oldTte = node . TimeToExpire ;
101+ // we know IsExpired is always called immediate before OnRead, so piggyback on the current time
101102 node . TimeToExpire = current + expiryCalculator . GetExpireAfterRead ( node . Key , node . Value , node . TimeToExpire - current ) ;
102- if ( oldTte . raw != node . TimeToExpire . raw )
103- {
104- wheel . Reschedule ( node ) ;
105- }
106103 }
107104
108105 [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
109106 public void OnWrite ( TimeOrderNode < K , V > node )
107+ {
108+ var current = Duration . SinceEpoch ( ) ;
109+ node . TimeToExpire = current + expiryCalculator . GetExpireAfterUpdate ( node . Key , node . Value , node . TimeToExpire - current ) ;
110+ }
111+
112+ [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
113+ public void AfterRead ( TimeOrderNode < K , V > node )
114+ {
115+ wheel . Reschedule ( node ) ;
116+ }
117+
118+ [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
119+ public void AfterWrite ( TimeOrderNode < K , V > node )
110120 {
111121 // if the node is not yet scheduled, it is being created
112122 // the time is set on create in case it is read before the buffer is processed
@@ -116,12 +126,7 @@ public void OnWrite(TimeOrderNode<K, V> node)
116126 }
117127 else
118128 {
119- var oldTte = node . TimeToExpire ;
120- node . TimeToExpire = current + expiryCalculator . GetExpireAfterUpdate ( node . Key , node . Value , node . TimeToExpire - current ) ;
121- if ( oldTte . raw != node . TimeToExpire . raw )
122- {
123- wheel . Reschedule ( node ) ;
124- }
129+ wheel . Reschedule ( node ) ;
125130 }
126131 }
127132
@@ -134,7 +139,7 @@ public void OnEvict(TimeOrderNode<K, V> node)
134139 [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
135140 public void ExpireEntries < P > ( ref ConcurrentLfuCore < K , V , TimeOrderNode < K , V > , P > cache ) where P : struct , INodePolicy < K , V , TimeOrderNode < K , V > >
136141 {
137- wheel . Advance ( ref cache , current ) ;
142+ wheel . Advance ( ref cache , Duration . SinceEpoch ( ) ) ;
138143 }
139144 }
140145}
0 commit comments