Exemplo n.º 1
0
        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 && Interlocked.CompareExchange(ref old.ReaderCount, int.MinValue, 0) == 0)
                {
                    // we do not want to move "old" to an element which still has not finished writing, since
                    // we must maintain the invariant that says _oldestRead.Changes have already been trimmed.
                    if (old.Later.Changes == null)
                        break;
                    // likewise, thanks to that same invariant, we first move forward, then take Changes...
                    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);
            }
        }