Example #1
0
        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);
Example #4
0
            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);