using System; using System.Collections; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Text; namespace NBTExplorer { public class SnapshotState : IDisposable { private SnapshotList _list; internal SnapshotState (SnapshotList list) { _list = list; _list.Begin(); } public void Dispose () { _list.End(); GC.SuppressFinalize(this); } } public class SnapshotList : Collection { private IList _snapshot; private IList _recycled; private int _snapshots; public SnapshotList () : base(new ProxyList()) { } public SnapshotList (IList list) : base(new ProxyList(new List(list))) { } public SnapshotList (int capacity) : base(new ProxyList(new List(capacity))) { } private new ProxyList Items { get { return base.Items as ProxyList; } } public IList Begin () { Modified(); _snapshot = Items.InnerList; _snapshots++; return _snapshot; } public void End () { _snapshots = Math.Max(0, _snapshots - 1); if (_snapshot == null) return; // The backing array was copied, keep around the old array if (_snapshot != Items.InnerList && _snapshots == 0) { _recycled = _snapshot; _recycled.Clear(); //for (int i = 0, n = _recycled.Count; i < n; i++) // _recycled[i] = default(T); } _snapshot = null; } public SnapshotState Snapshot () { return new SnapshotState(this); } private void Modified () { if (_snapshot == null || _snapshot != Items.InnerList) return; // Snapshot is in use, copy backing array to recycled array or create new backing array if (_recycled != null) { for (int i = 0; i < Count; i++) _recycled.Add(Items[i]); Items.InnerList = _recycled; _recycled = null; } else Resize(Items.Count); } private void Resize (int newSize) { IList oldList = Items.InnerList; List newList = new List(newSize); for (int i = 0, n = oldList.Count; i < n; i++) newList.Add(oldList[i]); Items.InnerList = newList; } protected override void InsertItem (int index, T item) { Modified(); base.InsertItem(index, item); } protected override void SetItem (int index, T item) { Modified(); base.SetItem(index, item); } protected override void RemoveItem (int index) { Modified(); base.RemoveItem(index); } protected override void ClearItems () { Modified(); base.ClearItems(); } private class ProxyList : IList { public IList InnerList { get; set; } public ProxyList () { InnerList = new List(); } public ProxyList (IList list) { InnerList = list; } public int IndexOf (K item) { return InnerList.IndexOf(item); } public void Insert (int index, K item) { InnerList.Insert(index, item); } public void RemoveAt (int index) { InnerList.RemoveAt(index); } public K this[int index] { get { return InnerList[index]; } set { InnerList[index] = value; } } public void Add (K item) { InnerList.Add(item); } public void Clear () { InnerList.Clear(); } public bool Contains (K item) { return InnerList.Contains(item); } public void CopyTo (K[] array, int arrayIndex) { InnerList.CopyTo(array, arrayIndex); } public int Count { get { return InnerList.Count; } } public bool IsReadOnly { get { return InnerList.IsReadOnly; } } public bool Remove (K item) { return InnerList.Remove(item); } public IEnumerator GetEnumerator () { return InnerList.GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator () { return InnerList.GetEnumerator(); } } } }