When updating a large struct, instead of updating in place, we can instead create a new node. Since nodes are not updated, no tearing can occur.
Time based expiry is a special case that is handled as follows:
The new INodePolicy.Clone method creates the replacement node to insert into the dictionary. For ExpireAfterPolicy this avoids calling expiry calculator on create, and we set current expiry to match old node. We also set GetNextInTimeOrder == self, this is a hack so that ExpireAfterPolicy.OnWrite knows the node was not created and is currently detached from the TimerWheel.
In ExpireAfterPolicy.OnWrite, check if next == self to schedule/reschedule. Schedule will just overwrite next to a valid node.
coverage: 98.702% (-0.4%) from 99.141%
when pulling 15edc9f55e4783c5c1617cebb4ef378bf4e319e3 on users/alexpeck/tornwrite3
into 07f8a1cc68229a29472077b2891690e0bfd46951 on main.
When updating a large struct, instead of updating in place, we can instead create a new node. Since nodes are not updated, no tearing can occur.
Time based expiry is a special case that is handled as follows:
INodePolicy.Clone
method creates the replacement node to insert into the dictionary. ForExpireAfterPolicy
this avoids calling expiry calculator on create, and we set current expiry to match old node. We also set GetNextInTimeOrder == self, this is a hack so thatExpireAfterPolicy.OnWrite
knows the node was not created and is currently detached from theTimerWheel
.ExpireAfterPolicy.OnWrite
, check if next == self to schedule/reschedule. Schedule will just overwrite next to a valid node.TODO: