rd-net/RdFramework/Impl/AsyncRdMap.cs (204 lines of code) (raw):

using System; using System.Collections; using System.Collections.Generic; using JetBrains.Annotations; 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 AsyncRdMap<K, V> : IRdBindable, IAsyncSource<MapEvent<K, V>>, IDictionary<K, V> where K : notnull { private readonly RdMapBackend myMap; private readonly AsyncSignal<MapEvent<K, V>> mySignal = new(); public AsyncRdMap(CtxReadDelegate<K> readKey, CtxWriteDelegate<K> writeKey, CtxReadDelegate<V> readValue, CtxWriteDelegate<V> writeValue) { myMap = new RdMapBackend(readKey, writeKey, readValue, writeValue); myMap.Change.Advise(Lifetime.Eternal, x => mySignal.Fire(x)); } public IAsyncSource<MapEvent<K, V>> Change => mySignal; public bool IsMaster = false; public RdId RdId { get { lock (myMap) return myMap.RdId; } set { lock (myMap) myMap.RdId = value; } } public void PreBind(Lifetime lf, IRdDynamic parent, string name) { lock (myMap) myMap.PreBind(lf, parent, name); } public void Bind() { lock (myMap) myMap.Bind(); } public void Identify(IIdentities identities, RdId id) { lock (myMap) myMap.Identify(identities, id); } public bool OptimizeNested { get => true; set { } } public bool ValueCanBeNull { get => myMap.ValueCanBeNull; set => myMap.ValueCanBeNull = value; } public bool Async { get => true; set { } } public RName Location { get { lock (myMap) return myMap.Location; } } public IProtocol? TryGetProto() { return myMap.TryGetProto(); } public bool TryGetSerializationContext(out SerializationCtx ctx) { return myMap.TryGetSerializationContext(out ctx); } public bool ContainsKey(K key) { return myMap.ContainsKey(key); } public void Add(K key, V value) { lock (myMap) myMap.Add(key, value); } public bool Remove(K key) { lock (myMap) return myMap.Remove(key); } public bool TryGetValue(K key, out V value) { return myMap.TryGetValue(key, out value); } public V this[K key] { get { lock (myMap) return myMap[key]; } set { lock (myMap) myMap[key] = value; } } public ICollection<K> Keys => myMap.Keys; public ICollection<V> Values => myMap.Values; void ICollection<KeyValuePair<K, V>>.Add(KeyValuePair<K, V> item) => Add(item.Key, item.Value); public void Clear() { lock (myMap) myMap.Clear(); } public bool Contains(KeyValuePair<K, V> item) => myMap.Contains(item); public void CopyTo(KeyValuePair<K, V>[] array, int arrayIndex) { myMap.CopyTo(array, arrayIndex); } public bool Remove(KeyValuePair<K, V> item) { lock (myMap) return myMap.Remove(item); } public int Count => myMap.Count; public bool IsReadOnly => myMap.IsReadOnly; public IEnumerator<KeyValuePair<K, V>> GetEnumerator() => myMap.GetEnumerator(); IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); [PublicAPI] public static AsyncRdMap<K, V> Read(SerializationCtx ctx, UnsafeReader reader) { return Read(ctx, reader, Polymorphic<K>.Read, Polymorphic<K>.Write, Polymorphic<V>.Read, Polymorphic<V>.Write); } [PublicAPI] public static AsyncRdMap<K,V> Read(SerializationCtx ctx, UnsafeReader reader, CtxReadDelegate<K> readKey, CtxWriteDelegate<K> writeKey, CtxReadDelegate<V> readValue, CtxWriteDelegate<V> writeValue) { var id = reader.ReadRdId(); return new AsyncRdMap<K, V>(readKey, writeKey, readValue, writeValue).WithId(id); } [PublicAPI] public static void Write(SerializationCtx ctx, UnsafeWriter writer, AsyncRdMap<K, V> value) { Assertion.Assert(!value.RdId.IsNil); writer.Write(value.RdId); } [PublicAPI] public CtxReadDelegate<K> ReadKeyDelegate => myMap.ReadKeyDelegate; [PublicAPI] public CtxWriteDelegate<K> WriteKeyDelegate => myMap.WriteKeyDelegate; [PublicAPI] public CtxReadDelegate<V> ReadValueDelegate => myMap.ReadValueDelegate; [PublicAPI] public CtxWriteDelegate<V> WriteValueDelegate => myMap.WriteValueDelegate; private class RdMapBackend : RdMap<K, V> { public RdMapBackend(CtxReadDelegate<K> readKey, CtxWriteDelegate<K> writeKey, CtxReadDelegate<V> readValue, CtxWriteDelegate<V> writeValue) : base(readKey, writeKey, readValue, writeValue) { OptimizeNested = true; Async = true; } protected override void AssertBindingThread() { } protected override void AssertThreading() { } public override void OnWireReceived(IProtocol proto, SerializationCtx ctx, UnsafeReader stream, IRdWireableDispatchHelper dispatchHelper) { lock (this) base.OnWireReceived(proto, ctx, stream, new DelegatingDispatchHelper(dispatchHelper)); } } private class DelegatingDispatchHelper : IRdWireableDispatchHelper { private readonly IRdWireableDispatchHelper myDispatchHelper; public RdId RdId => myDispatchHelper.RdId; public Lifetime Lifetime => myDispatchHelper.Lifetime; public DelegatingDispatchHelper(IRdWireableDispatchHelper dispatchHelper) { myDispatchHelper = dispatchHelper; } public void Dispatch(IScheduler? scheduler, Action action) { myDispatchHelper.Dispatch(SynchronousScheduler.Instance, action); } } public void Print(PrettyPrinter printer) { lock (myMap) myMap.Print(printer); } public void AdviseOn(Lifetime lifetime, IScheduler scheduler, Action<MapEvent<K, V>> action) { lock (myMap) { myMap.Advise(lifetime, e => { scheduler.Queue(() => action(e)); }); } } }