protected override ValueTask OnReceiveAsync(ReadOnlySequence <byte> payload, int messageId) { if (messageId != 0) { // request/response TaskCompletionSource <IMemoryOwner <byte> > tcs; lock (_awaitingResponses) { if (_awaitingResponses.TryGetValue(messageId, out tcs)) { _awaitingResponses.Remove(messageId); } else { tcs = null; messageId = 0; // treat as Broadcast } } if (tcs != null) { IMemoryOwner <byte> lease = null; try { // only if we successfully hand it over // to the TCS is it considered "not our // problem anymore" - otherwise: we need // to dispose lease = payload.Lease(); if (tcs.TrySetResult(lease)) { lease = null; } } finally { if (lease != null) { try { lease.Dispose(); } catch { } } } } } if (messageId == 0) { // unsolicited Broadcast?.Invoke(payload.Lease()); } return(default);
protected sealed override ValueTask OnReceiveAsync(ReadOnlySequence <byte> payload, int messageId) { // DF will hate me for this, but... it won't be awaited, so : don't create the task async void AwaitedResponse( ValueTask <IMemoryOwner <byte> > ppendingResponse, int mmessageId, IMemoryOwner <byte> rrequest) { try { using (rrequest) { var response = await ppendingResponse; await WriteAsync(response, mmessageId); } } catch { } // nom nom nom } void DisposeOnCompletion(ValueTask task, ref IMemoryOwner <byte> message) { task.AsTask().ContinueWith((t, s) => ((IMemoryOwner <byte>)s)?.Dispose(), message); message = null; // caller no longer owns it, logically; don't wipe on exit } var msg = payload.Lease(); try { if (messageId == 0) { var pendingAction = _server.OnReceiveAsync(msg); if (!pendingAction.IsCompletedSuccessfully) { DisposeOnCompletion(pendingAction, ref msg); } } else { var pendingResponse = _server.OnReceiveForReplyAsync(msg); if (pendingResponse.IsCompletedSuccessfully) { var pendingWrite = WriteAsync(pendingResponse.Result, messageId); if (!pendingWrite.IsCompletedSuccessfully) { DisposeOnCompletion(pendingWrite, ref msg); } } else { AwaitedResponse(pendingResponse, messageId, msg); msg = null; } } } finally { // might have been wiped if we went async msg?.Dispose(); } return(default);
protected sealed override ValueTask OnReceiveAsync(ReadOnlySequence <byte> payload) { //void DisposeOnCompletion(/*Value*/Task task, ref IMemoryOwner<byte> message) //{ // task/*.AsTask()*/.ContinueWith((t, s) => ((IMemoryOwner<byte>)s)?.Dispose(), message); // message = null; // caller no longer owns it, logically; don't wipe on exit //} var msg = payload.Lease(); // copy to buffer pool, ProcessAsync must release it // https://devblogs.microsoft.com/pfxteam/task-run-vs-task-factory-startnew/ Task.Run(() => { PostilionMessage pm; try { pm = new PostilionMessage(); pm.ParseFromBuffer(msg.Memory.Span); } finally { msg.Dispose(); // release back to buffer pool } _messageHandler.ProcessMessage(pm); // todo: make async? }); // parse & process message on worker thread, let this thread read next message from pipeline //try //{ //var pendingAction = _sink.ProcessAsync(msg); //if (!pendingAction.IsCompletedSuccessfully) // DisposeOnCompletion(pendingAction, ref msg); //} //finally //{ // might have been wiped if we went async // msg?.Dispose(); //} return(default);
protected sealed override ValueTask OnReceiveAsync(ReadOnlySequence <byte> payload, int messageId) { async void AwaitServerToReply(ValueTask <IMemoryOwner <byte> > pendingResponse, int msgId, IMemoryOwner <byte> message) { try { using (message) { var response = await pendingResponse; await WriteAsync(response, msgId); } } catch { } } void DisposeOnCompletion(ValueTask task, ref IMemoryOwner <byte> message) { task.AsTask().ContinueWith((t, s) => ((IMemoryOwner <byte>)s)?.Dispose(), message); message = null; // caller no longer owns it, logically; don't wipe on exit } var msg = payload.Lease(); try { if (messageId == 0) { var pending = _server.OnReceiveAsync(msg); if (!pending.IsCompletedSuccessfully) { DisposeOnCompletion(pending, ref msg); } } else { var pending = _server.OnReceiveForReplyAsync(msg); if (pending.IsCompletedSuccessfully) { var writeResult = WriteAsync(pending.Result, messageId); if (!writeResult.IsCompletedSuccessfully) { DisposeOnCompletion(writeResult, ref msg); } } else { AwaitServerToReply(pending, messageId, msg); msg = null; } } } finally { if (msg != null) { try { msg.Dispose(); } catch { } } } return(default);