public static void TrimCopies() { bool tookFlag = false; try { try { } finally { tookFlag = Interlocked.CompareExchange(ref _trimFlag, 1, 0) == 0; } if (!tookFlag) { return; } var old = _oldestRead; SimpleHashSet toTrim = null; while (old != _current && old.Later.Changes != null && Interlocked.CompareExchange(ref old.ReaderCount, int.MinValue, 0) == 0) { // NB any transaction that holds a WriteTicker with Changes == null also // has a ReadTicket with a smaller stamp. but we don't depend on that here. old = old.Later; if (toTrim == null) { toTrim = new SimpleHashSet(); } toTrim.UnionWith(old.Changes); } if (toTrim == null) { return; } old.Changes = null; _oldestRead = old; var version = old.Stamp; toTrim.TrimCopies(version); } finally { if (tookFlag) { Interlocked.Exchange(ref _trimFlag, 0); } } }
/// <summary> /// Runs the action, and returns a set of IShieldeds that the action enlisted. /// It will make sure to restore original enlisted items, merged with the ones /// that the action enlisted, before returning. This is important to make sure /// all thread-local state is cleared on transaction exit. The isolated action /// may still cause outer transaction's commutes to degenerate. /// </summary> internal static SimpleHashSet IsolatedRun(Action act) { var isolated = new SimpleHashSet(); var originalItems = _context.Items.Enlisted; var oldEnforce = _enforceTracking; var oldBlock = _blockCommute; try { Shield._context.Items.Enlisted = isolated; Shield._blockCommute = true; Shield._enforceTracking = true; act(); } finally { originalItems.UnionWith(isolated); Shield._context.Items.Enlisted = originalItems; Shield._blockCommute = oldBlock; Shield._enforceTracking = oldEnforce; } return(isolated); }