using System;
using System.Collections.Generic;
using System.Threading;
using JetBrains.Annotations;
using JetBrains.Collections.Synchronized;
using JetBrains.Collections.Viewable;
using JetBrains.Diagnostics;
using JetBrains.Lifetimes;
using JetBrains.Rd.Base;
namespace JetBrains.Rd.Impl
{
public class Protocol : IProtocol
{
public static readonly ILog Logger = Log.GetLog("protocol");
public static readonly ILog InitLogger = Logger.GetSublogger("INIT");
public static LogWithLevel? InitTrace = InitLogger.WhenTrace();
///
/// Should match textual RdId of protocol intern root in Kotlin/js/cpp counterpart
///
const string ProtocolInternRootRdId = "ProtocolInternRoot";
const string ContextHandlerRdId = "ProtocolContextHandler";
internal const string ProtocolExtCreatedRdId = "ProtocolExtCreated";
///
/// Should match whatever is in rd-gen for ProtocolInternScope
///
const string ProtocolInternScopeStringId = "Protocol";
public Lifetime Lifetime { get; }
public RdEntitiesRegistrar RdEntitiesRegistrar { get; }
private readonly Protocol? myParentProtocol;
private readonly Dictionary myExtensions = new();
public Protocol(string name, ISerializers serializers, IIdentities identities, IScheduler scheduler,
IWire wire, Lifetime lifetime, params RdContextBase[] initialContexts)
: this(name, serializers, identities, scheduler, wire, lifetime, null, null, initialContexts)
{ }
internal Protocol(string name, ISerializers serializers, IIdentities identities, IScheduler scheduler,
IWire wire, Lifetime lifetime, Protocol? parentProtocol, RdSignal? parentExtConfirmation = null, params RdContextBase[] initialContexts)
{
Lifetime = lifetime;
Name = name ?? throw new ArgumentNullException(nameof(name));
Location = new RName(name);
Serializers = serializers ?? throw new ArgumentNullException(nameof(serializers));
Identities = identities ?? throw new ArgumentNullException(nameof(identities));
Scheduler = scheduler ?? throw new ArgumentNullException(nameof(scheduler));
Wire = wire ?? throw new ArgumentNullException(nameof(wire));
myParentProtocol = parentProtocol;
RdEntitiesRegistrar = parentProtocol?.RdEntitiesRegistrar ?? new RdEntitiesRegistrar();
SerializationContext = parentProtocol?.SerializationContext ?? new SerializationCtx(this, new Dictionary>() {{ProtocolInternScopeStringId, CreateProtocolInternRoot(lifetime)}});
Contexts = parentProtocol?.Contexts ?? new ProtocolContexts(SerializationContext);
wire.Contexts = Contexts;
if (parentProtocol?.SerializationContext == null)
SerializationContext.InternRoots[ProtocolInternScopeStringId].BindTopLevel(lifetime, this, ProtocolInternRootRdId);
foreach (var rdContextBase in initialContexts) rdContextBase.RegisterOn(Contexts);
if (parentProtocol?.Contexts == null)
BindContexts(lifetime);
OutOfSyncModels = new ViewableSet();
ExtCreated = parentProtocol?.ExtCreated ?? new Signal();
ExtConfirmation = parentExtConfirmation ?? this.CreateExtSignal();
ExtIsLocal = new ThreadLocal(() => false);
ExtConfirmation.Advise(lifetime, message =>
{
ExtCreated.Fire(new ExtCreationInfoEx(message, ExtIsLocal.Value));
});
using (AllowBindCookie.Create())
ExtConfirmation.BindTopLevel(lifetime, this, ProtocolExtCreatedRdId);
if (wire is IWireWithDelayedDelivery wireWithMessageBroker)
wireWithMessageBroker.StartDeliveringMessages();
}
public bool TryGetSerializationContext(out SerializationCtx ctx)
{
ctx = SerializationContext;
return true;
}
private InternRoot