File: Telemetry\PersistenceChannel\SnapshottingCollection.cs
Web Access
Project: ..\..\..\src\Cli\dotnet\dotnet.csproj (dotnet)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
#nullable disable
 
using System.Collections;
using System.Diagnostics;
 
namespace Microsoft.DotNet.Cli.Telemetry.PersistenceChannel;
 
internal abstract class SnapshottingCollection<TItem, TCollection> : ICollection<TItem>
    where TCollection : class, ICollection<TItem>
{
    protected readonly TCollection Collection;
    protected TCollection snapshot;
 
    protected SnapshottingCollection(TCollection collection)
    {
        Debug.Assert(collection != null, "collection");
        Collection = collection;
    }
 
    public int Count => GetSnapshot().Count;
 
    public bool IsReadOnly => false;
 
    public void Add(TItem item)
    {
        lock (Collection)
        {
            Collection.Add(item);
            snapshot = default;
        }
    }
 
    public void Clear()
    {
        lock (Collection)
        {
            Collection.Clear();
            snapshot = default;
        }
    }
 
    public bool Contains(TItem item)
    {
        return GetSnapshot().Contains(item);
    }
 
    public void CopyTo(TItem[] array, int arrayIndex)
    {
        GetSnapshot().CopyTo(array, arrayIndex);
    }
 
    public bool Remove(TItem item)
    {
        lock (Collection)
        {
            bool removed = Collection.Remove(item);
            if (removed)
            {
                snapshot = default;
            }
 
            return removed;
        }
    }
 
    public IEnumerator<TItem> GetEnumerator()
    {
        return GetSnapshot().GetEnumerator();
    }
 
    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }
 
    protected abstract TCollection CreateSnapshot(TCollection collection);
 
    protected TCollection GetSnapshot()
    {
        TCollection localSnapshot = snapshot;
        if (localSnapshot == null)
        {
            lock (Collection)
            {
                snapshot = CreateSnapshot(Collection);
                localSnapshot = snapshot;
            }
        }
 
        return localSnapshot;
    }
}