diff --git a/rd-kt/rd-framework/src/main/kotlin/com/jetbrains/rd/framework/impl/RdTask.kt b/rd-kt/rd-framework/src/main/kotlin/com/jetbrains/rd/framework/impl/RdTask.kt index 6ea884525..d9e196061 100644 --- a/rd-kt/rd-framework/src/main/kotlin/com/jetbrains/rd/framework/impl/RdTask.kt +++ b/rd-kt/rd-framework/src/main/kotlin/com/jetbrains/rd/framework/impl/RdTask.kt @@ -71,7 +71,7 @@ abstract class WiredRdTask( } class CallSiteWiredRdTask( - private val outerLifetime: Lifetime, + val outerLifetime: Lifetime, call: RdCall, rdid: RdId, wireScheduler: IScheduler @@ -364,15 +364,11 @@ class RdCall(internal val requestSzr: ISerializer = Polymorphi val taskId = proto.identity.next(RdId.Null) - val bindLifetime = bindLifetime - val intersectedDef = lifetime.defineIntersection(bindLifetime) - val task = CallSiteWiredRdTask(intersectedDef.lifetime, this, taskId, scheduler ?: proto.scheduler) - task.result.advise(intersectedDef.lifetime) { - if (it !is RdTaskResult.Success || !it.value.isBindable()) { - intersectedDef.terminate(true) - } + val task = createCallSite(lifetime) { callsiteLifetime -> + CallSiteWiredRdTask(callsiteLifetime, this, taskId, scheduler ?: proto.scheduler) } - intersectedDef.lifetime.executeIfAlive { + + task.outerLifetime.executeIfAlive { proto.wire.send(rdid) { buffer -> logSend.trace { "call `$location`::($rdid) send${sync.condstr {" SYNC"}} request '$taskId' : ${request.printToString()} " } taskId.write(buffer) @@ -383,6 +379,24 @@ class RdCall(internal val requestSzr: ISerializer = Polymorphi return task } + private inline fun createCallSite( + requestLifetime: Lifetime, + createTask: (Lifetime) -> CallSiteWiredRdTask + ): CallSiteWiredRdTask { + if (requestLifetime.isEternal) + return createTask(bindLifetime) + + val intersectedDef = Lifetime.defineIntersection(requestLifetime, bindLifetime) + val task = createTask(intersectedDef.lifetime) + task.result.advise(intersectedDef.lifetime) { + if (it !is RdTaskResult.Success || !it.value.isBindable()) { + intersectedDef.terminate(true) + } + } + + return task + } + /** * Assigns a handler that executes the API asynchronously. */ diff --git a/rd-net/RdFramework/Tasks/RdCall.cs b/rd-net/RdFramework/Tasks/RdCall.cs index c048e305a..c219bcc8e 100644 --- a/rd-net/RdFramework/Tasks/RdCall.cs +++ b/rd-net/RdFramework/Tasks/RdCall.cs @@ -200,18 +200,9 @@ private IRdTask StartInternal(Lifetime requestLifetime, TReq request, ISch var taskId = proto.Identities.Next(RdId.Nil); - var intersectedDef = Lifetime.DefineIntersection(requestLifetime, myBindLifetime); - var task = new WiredRdTask.CallSite(intersectedDef.Lifetime, this, taskId, scheduler ?? proto.Scheduler); - task.Result.Advise(intersectedDef.Lifetime, result => - { - if (result.Status != RdTaskStatus.Success || !result.Result.IsBindable()) - { - intersectedDef.AllowTerminationUnderExecution = true; - intersectedDef.Terminate(); - } - }); + var task = CreateCallSite(requestLifetime, (lifetime) => new WiredRdTask.CallSite(lifetime, this, taskId, scheduler ?? proto.Scheduler)); - using var cookie = intersectedDef.UsingExecuteIfAlive(); + using var cookie = task.Lifetime.UsingExecuteIfAlive(); if (cookie.Succeed) { proto.Wire.Send(RdId, (writer) => @@ -226,6 +217,25 @@ private IRdTask StartInternal(Lifetime requestLifetime, TReq request, ISch return task; } + private WiredRdTask.CallSite CreateCallSite(Lifetime requestLifetime, Func.CallSite> createTask) + { + if (requestLifetime.IsEternal) + return createTask(myBindLifetime); + + var intersectedDef = Lifetime.DefineIntersection(requestLifetime, myBindLifetime); + var task = createTask(intersectedDef.Lifetime); + task.Result.Advise(intersectedDef.Lifetime, result => + { + if (result.Status != RdTaskStatus.Success || !result.Result.IsBindable()) + { + intersectedDef.AllowTerminationUnderExecution = true; + intersectedDef.Terminate(); + } + }); + + return task; + } + public static RdCall Read(SerializationCtx ctx, UnsafeReader reader, CtxReadDelegate readRequest, CtxWriteDelegate writeRequest, CtxReadDelegate readResponse, CtxWriteDelegate writeResponse) { return new RdCall(readRequest, writeRequest, readResponse, writeResponse).WithId(reader.ReadRdId()); diff --git a/rd-net/RdFramework/Tasks/WiredRdTask.cs b/rd-net/RdFramework/Tasks/WiredRdTask.cs index 6f215bbb3..0d4fad7cb 100644 --- a/rd-net/RdFramework/Tasks/WiredRdTask.cs +++ b/rd-net/RdFramework/Tasks/WiredRdTask.cs @@ -64,6 +64,8 @@ internal class CallSite : WiredRdTask { private readonly Lifetime myOuterLifetime; + public Lifetime Lifetime => myOuterLifetime; + public CallSite(Lifetime outerLifetime, RdCall call, RdId rdId, IScheduler wireScheduler) : base(call, rdId, wireScheduler) { myOuterLifetime = outerLifetime;