public static void Write(this UnsafeWriter writer, RdId id) { id.Write(writer); }
public override void Identify(IIdentities identities, RdId id) { EnsureBindableChildren(); base.Identify(identities, id); }
public override void Identify(IIdentities identities, RdId id) { ((IReflectionBindable)this).EnsureBindableChildren(); base.Identify(identities, id); }
public static RdId ReadRdId(this UnsafeReader reader) { return(RdId.Read(reader)); }
public QueueItem(RdId id, byte[] bytes, KeyValuePair <RdContextBase, object>[] storedContext) { Id = id; Bytes = bytes; StoredContext = storedContext; }
public static void Write(SerializationCtx ctx, UnsafeWriter writer, RdCall <TReq, TRes> value) { RdId.Write(writer, value.RdId); }
public Endpoint(Lifetime bindLifetime, RdCall <TReq, TRes> call, RdId rdId, IScheduler wireScheduler) : base(call, rdId, wireScheduler) { myDef = bindLifetime.CreateNested(); myCall.Wire.Advise(Lifetime, this); Lifetime.TryOnTermination(() => ResultInternal.SetIfEmpty(RdTaskResult <TRes> .Cancelled())); Result.AdviseOnce(Lifetime.Eternal, taskResult => { var potentiallyBindable = taskResult.Result; if (potentiallyBindable.IsBindable()) { potentiallyBindable.IdentifyPolymorphic(myCall.Proto.Identities, myCall.RdId.Mix(RdId.ToString())); potentiallyBindable.BindPolymorphic(Lifetime, myCall, RdId.ToString()); } else { myDef.Terminate(); } Trace(RdReactiveBase.ourLogSend, "send response", taskResult); myWire.Send(RdId, writer => { RdTaskResult <TRes> .Write(myCall.WriteResponseDelegate, myCall.SerializationContext, writer, taskResult); }); }); }
public override void Identify(IIdentities identities, RdId id) { myValue.Identify(identities, id); }
public override void Identify(IIdentities identities, RdId id) { Property.Identify(identities, id); base.Identify(identities, id); }
private void Register(Type type, ISerializersContainer serializers) { var instanceSerializer = type.IsInterface || type.IsAbstract; var serializerPair = myReflectionSerializersFactory.GetOrRegisterSerializerPair(type, instanceSerializer); ReflectionUtil.InvokeGenericThis(serializers, nameof(serializers.Register), type, new[] { serializerPair.Reader, serializerPair.Writer, RdId.DefineByFqn(type).Value }); }
public static void IdentifyEx <T>([CanBeNull] this T[] items, IIdentities ids, RdId id) where T : IRdBindable { items.Identify0(ids, id); }
private static void Identify0([CanBeNull] this IEnumerable items, IIdentities ids, RdId id) { if (items == null) { return; } var i = 0; foreach (var x in items) { (x as IRdBindable).IdentifyEx(ids, id.Mix(i++)); } }
/// <summary> /// Register serializers for either <see cref="RdExtAttribute"/> or <see cref="RdModelAttribute"/> /// </summary> private void RegisterModelSerializer <T>() { // place null marker to detect circular dependencies mySerializers.Add(typeof(T), null); TypeInfo typeInfo = typeof(T).GetTypeInfo(); ReflectionSerializerVerifier.AssertRoot(typeInfo); bool allowNullable = ReflectionSerializerVerifier.HasRdModelAttribute(typeInfo); var intrinsicSerializer = TryGetIntrinsicSerializer(typeInfo); if (intrinsicSerializer != null) { mySerializers[typeof(T)] = intrinsicSerializer; return; } var memberInfos = GetBindableMembers(typeInfo); var memberSetters = memberInfos.Select(ReflectionUtil.GetSetter).ToArray(); var memberGetters = memberInfos.Select(ReflectionUtil.GetGetter).ToArray(); // todo: consider using IL emit var memberDeserializers = new CtxReadDelegate <object> [memberInfos.Length]; var memberSerializers = new CtxWriteDelegate <object> [memberInfos.Length]; for (var index = 0; index < memberInfos.Length; index++) { var mi = memberInfos[index]; var returnType = ReflectionUtil.GetReturnType(mi); var serPair = GetOrCreateMemberSerializer(mi, serializerType: returnType, allowNullable: allowNullable); memberDeserializers[index] = ConvertReader(returnType, serPair.Reader); memberSerializers[index] = ConvertWriter(returnType, serPair.Writer); } var type = typeInfo.AsType(); CtxReadDelegate <T> readerDelegate = (ctx, unsafeReader) => { // todo: support non-default constructors var instance = Activator.CreateInstance(type); var bindableInstance = instance as IRdBindable; RdId id = default(RdId); if (bindableInstance != null) { id = unsafeReader.ReadRdId(); } for (var index = 0; index < memberDeserializers.Length; index++) { var value = memberDeserializers[index](ctx, unsafeReader); memberSetters[index](instance, value); } bindableInstance?.WithId(id); return((T)instance); }; CtxWriteDelegate <T> writerDelegate = (ctx, unsafeWriter, value) => { if (value is IRdBindable bindableInstance) { unsafeWriter.Write(bindableInstance.RdId); } for (var i = 0; i < memberDeserializers.Length; i++) { var memberValue = memberGetters[i](value); memberSerializers[i](ctx, unsafeWriter, memberValue); } }; mySerializers[type] = new SerializerPair(readerDelegate, writerDelegate); }
public RdId Next(RdId parent) { return(parent.Mix(Interlocked.Add(ref myId, 2))); }
//identify method public override void Identify(IIdentities ids, RdId id) { _Log.IdentifyEx(ids, id.Mix(".log")); }
internal Lifetime Subscribe(Lifetime outerLifetime) { var taskWireSubscriptionDefinition = outerLifetime.CreateNested(); var externalCancellation = outerLifetime.CreateNested(); myCall.Wire.Advise(taskWireSubscriptionDefinition.Lifetime, this); //this lifetimeDef listen only one value outerLifetime.TryOnTermination(() => ResultInternal.SetIfEmpty(RdTaskResult <TRes> .Cancelled())); //todo Result.AdviseOnce(Lifetime.Eternal, taskResult => { taskWireSubscriptionDefinition.Terminate(); //no need to listen result or cancellation from wire var potentiallyBindable = taskResult.Result; if (potentiallyBindable.IsBindable()) { if (myIsEndpoint) { potentiallyBindable.IdentifyPolymorphic(myCall.Proto.Identities, myCall.RdId.Mix(RdId.ToString())); } potentiallyBindable.BindPolymorphic(externalCancellation.Lifetime, myCall, RdId.ToString()); } if (myIsEndpoint) { if (taskResult.Status == RdTaskStatus.Canceled) { externalCancellation.Terminate(); } Trace(RdReactiveBase.ourLogSend, "send response", taskResult); myWire.Send(RdId, writer => { RdTaskResult <TRes> .Write(myCall.WriteResponseDelegate, myCall.SerializationContext, writer, taskResult); }); } else if (taskResult.Status == RdTaskStatus.Canceled) //we need to transfer cancellation to the other side { Trace(RdReactiveBase.ourLogSend, "send cancellation"); myWire.Send(RdId, writer => { writer.Write(Unit.Instance); }); //send cancellation to the other side } }); return(externalCancellation.Lifetime); }
internal void Register(Type type, ISerializers serializers) { var serializerPair = myReflectionSerializersFactory.GetOrRegisterSerializerPair(type); ReflectionUtil.InvokeGenericThis(serializers, nameof(serializers.Register), type, new[] { serializerPair.Reader, serializerPair.Writer, RdId.DefineByFqn(type).Value }); }
public void AddType(Type type) { myRdIdToTypeMapping[RdId.Define(type)] = type; }
public override void OnWireReceived(UnsafeReader reader) { var taskId = RdId.Read(reader); var value = ReadRequestDelegate(SerializationContext, reader); if (LogReceived.IsTraceEnabled()) { LogReceived.Trace("endpoint `{0}`::({1}), taskId={2}, request = {3}", Location, RdId, taskId, value.PrintToString()); } var taskLifetimeDef = myBindLifetime.CreateNested(); //subscribe for lifetime cancellation new WiredLifetime(taskLifetimeDef, taskId, this, Wire); RdTask <TRes> rdTask; using (UsingDebugInfo()) //now supports only sync handlers { try { rdTask = Handler(taskLifetimeDef.Lifetime, value); } catch (Exception e) { rdTask = RdTask <TRes> .Faulted(e); } } rdTask.Result.Advise(taskLifetimeDef.Lifetime, result => { if (LogSend.IsTraceEnabled()) { LogSend.Trace("endpoint `{0}`::({1}), taskId={2}, response = {3}", Location, RdId, taskId, result.PrintToString()); } RdTaskResult <TRes> validatedResult; try { if (result.Status == RdTaskStatus.Success) { AssertNullability(result.Result); } validatedResult = result; } catch (Exception e) { LogSend.Error(e); validatedResult = RdTaskResult <TRes> .Faulted(e); } Wire.Send(taskId, writer => { RdTaskResult <TRes> .Write(WriteResponseDelegate, SerializationContext, writer, validatedResult); }); taskLifetimeDef.Terminate(); //need to terminate to unsubscribe lifetime listener - not for bindable entries }); }
//on poller thread public void Dispatch(RdId id, byte[] msg) { Assertion.Require(!id.IsNil, "!id.IsNil"); lock (myLock) { var s = mySubscriptions.GetOrDefault(id); if (s == null) { var currentBroker = myBroker.GetOrCreate(id, () => new Mq()); currentBroker.DefaultSchedulerMessages.Add(msg); myScheduler.Queue(() => { byte[] msg1; lock (myLock) { if (currentBroker.DefaultSchedulerMessages.Count > 0) { msg1 = currentBroker.DefaultSchedulerMessages[0]; currentBroker.DefaultSchedulerMessages.RemoveAt(0); } else { msg1 = null; } } if (!mySubscriptions.TryGetValue(id, out var subscription)) { myLogger.Trace("No handler for id: {0}", id); } else if (msg1 != null) { Invoke(subscription, msg1, sync: subscription.WireScheduler == myScheduler); } lock (myLock) { if (currentBroker.DefaultSchedulerMessages.Count == 0) { if (myBroker.Remove(id)) { if (subscription != null) { foreach (var m in currentBroker.CustomSchedulerMessages) { Assertion.Assert(subscription.WireScheduler != myScheduler, "subscription.Scheduler != myScheduler for {0}", subscription); Invoke(subscription, m); } } } } } }); } else // s != null { if (s.WireScheduler == myScheduler || s.WireScheduler.OutOfOrderExecution) { Invoke(s, msg); } else { var mq = myBroker.GetOrDefault(id); if (mq != null) { mq.CustomSchedulerMessages.Add(msg); } else { Invoke(s, msg); } } } } }
public void Identify(IIdentities identities, RdId id) => Delegate.Identify(identities, id);