rd-net/RdFramework/Impl/RdSet.cs (190 lines of code) (raw):

using System; using System.Collections; using System.Collections.Generic; using JetBrains.Annotations; using JetBrains.Collections.Synchronized; using JetBrains.Collections.Viewable; using JetBrains.Diagnostics; using JetBrains.Lifetimes; using JetBrains.Rd.Base; using JetBrains.Rd.Util; using JetBrains.Serialization; namespace JetBrains.Rd.Impl { public class RdSet<T> : RdReactiveBase, IViewableSet<T> where T: notnull { private readonly IViewableSet<T> mySet; public RdSet(CtxReadDelegate<T> readValue, CtxWriteDelegate<T> writeValue) { ValueCanBeNull = false; ReadValueDelegate = readValue; WriteValueDelegate = writeValue; mySet = new ViewableSet<T>(new SynchronizedSet<T>() /*to have thread-safe print*/); } #region Serializers public CtxReadDelegate<T> ReadValueDelegate { get; private set; } public CtxWriteDelegate<T> WriteValueDelegate { get; private set; } public static RdSet<T> Read(SerializationCtx ctx, UnsafeReader reader) { return Read(ctx, reader, Polymorphic<T>.Read, Polymorphic<T>.Write); } public static RdSet<T> Read(SerializationCtx ctx, UnsafeReader reader, CtxReadDelegate<T> readValue, CtxWriteDelegate<T> writeValue) { var id = reader.ReadRdId(); return new RdSet<T>(readValue, writeValue).WithId(id); } public static void Write(SerializationCtx ctx, UnsafeWriter writer, RdSet<T> value) { Assertion.Assert(!value.RdId.IsNil); writer.Write(value.RdId); } #endregion #region Mastering public bool IsMaster = false; #endregion #region Init public bool OptimizeNested { [PublicAPI] get; set; } protected override void PreInit(Lifetime lifetime, IProtocol proto) { base.PreInit(lifetime, proto); proto.Wire.Advise(lifetime, this); } protected override void Init(Lifetime lifetime, IProtocol proto, SerializationCtx ctx) { base.Init(lifetime, proto, ctx); using (UsingLocalChange()) { Advise(lifetime, it => { if (!IsLocalChange) return; proto.Wire.Send(RdId, (stream) => { stream.WriteInt32((int)it.Kind); WriteValueDelegate(ctx, stream, it.Value); SendTrace?.Log($"{this} :: {it.Kind} :: {it.Value.PrintToString()}"); }); }); } } public override void OnWireReceived(IProtocol proto, SerializationCtx ctx, UnsafeReader stream, IRdWireableDispatchHelper dispatchHelper) { var kind = (AddRemove) stream.ReadInt(); var value = ReadValueDelegate(ctx, stream); ReceiveTrace?.Log($"OnWireReceived:: {this} :: {kind} :: {value.PrintToString()}"); dispatchHelper.Dispatch(() => { ReceiveTrace?.Log($"Dispatched:: {this} :: {kind} :: {value.PrintToString()}"); switch (kind) { case AddRemove.Add: mySet.Add(value); break; case AddRemove.Remove: mySet.Remove(value); break; default: throw new ArgumentOutOfRangeException(); } }); } #endregion #region Read delegation IEnumerator IEnumerable.GetEnumerator() { return mySet.GetEnumerator(); } public IEnumerator<T> GetEnumerator() { return mySet.GetEnumerator(); } public bool Contains(T item) { return mySet.Contains(item); } public void CopyTo(T[] array, int arrayIndex) { mySet.CopyTo(array, arrayIndex); } public int Count => mySet.Count; public bool IsReadOnly => mySet.IsReadOnly; public ISource<SetEvent<T>> Change => mySet.Change; #endregion #region Write delegation public bool Remove(T item) { using (UsingLocalChange()) return mySet.Remove(item); } // ReSharper disable once AssignNullToNotNullAttribute void ICollection<T>. Add(T item) { AssertNullability(item); using (UsingLocalChange()) mySet.Add(item); } public bool Add(T item) { AssertNullability(item); using (UsingLocalChange()) return mySet.Add(item); } public void ExceptWith(IEnumerable<T> other) { using (UsingLocalChange()) mySet.ExceptWith(other); } public void IntersectWith(IEnumerable<T> other) { using (UsingLocalChange()) mySet.IntersectWith(other); } public void SymmetricExceptWith(IEnumerable<T> other) { using (UsingLocalChange()) mySet.SymmetricExceptWith(other); } public void UnionWith(IEnumerable<T> other) { using (UsingLocalChange()) mySet.UnionWith(other); } public void Clear() { using (UsingLocalChange()) mySet.Clear(); } #endregion #region ISet Read delegation public bool IsProperSubsetOf(IEnumerable<T> other) => mySet.IsProperSubsetOf(other); public bool IsProperSupersetOf(IEnumerable<T> other) => mySet.IsProperSupersetOf(other); public bool IsSubsetOf(IEnumerable<T> other) => mySet.IsSubsetOf(other); public bool IsSupersetOf(IEnumerable<T> other) => mySet.IsSupersetOf(other); public bool Overlaps(IEnumerable<T> other) => mySet.Overlaps(other); public bool SetEquals(IEnumerable<T> other) => mySet.SetEquals(other); #endregion public void Advise(Lifetime lifetime, Action<SetEvent<T>> handler) { if (IsBound) AssertThreading(); using (UsingDebugInfo()) mySet.Advise(lifetime, handler); } protected override string ShortName => "set"; public override void Print(PrettyPrinter printer) { base.Print(printer); if (!printer.PrintContent) return; printer.Print(" ["); if (Count > 0) printer.Println(); using (printer.IndentCookie()) { foreach (var v in this) { v.PrintEx(printer); printer.Println(); } } printer.Println("]"); } } }