Пример #1
0
        public SimpleOutputs(IActorRef actor, IPump pump)
        {
            Actor = actor;
            Pump  = pump;

            SubReceive          = new SubReceive(WaitingExposedPublisher);
            NeedsDemand         = DefaultOutputTransferStates.NeedsDemand(this);
            NeedsDemandOrCancel = DefaultOutputTransferStates.NeedsDemandOrCancel(this);
        }
Пример #2
0
        /// <summary>
        /// TBD
        /// </summary>
        /// <param name="inputCount">TBD</param>
        /// <param name="bufferSize">TBD</param>
        /// <param name="pump">TBD</param>
        protected InputBunch(int inputCount, int bufferSize, IPump pump)
        {
            _inputCount = inputCount;

            _states = new State[inputCount];
            _inputs = new BatchingInputBuffer[inputCount];
            for (var i = 0; i < inputCount; i++)
            {
                _inputs[i] = new AnonymousBatchingInputBuffer(bufferSize, pump, i, this);
            }

            AllOfMarkedInputs = new LambdaTransferState(
                isCompleted: () => _markedDepleted > 0,
                isReady: () => _markedPending == _markCount);

            AnyOfMarkedInputs = new LambdaTransferState(
                isCompleted: () => _markedDepleted == _markCount && _markedPending == 0,
                isReady: () => _markedPending > 0);

            // FIXME: Eliminate re-wraps
            SubReceive = new SubReceive(msg => msg.Match()
                                        .With <FanIn.OnSubscribe>(subscribe => _inputs[subscribe.Id].SubReceive.CurrentReceive(new Actors.OnSubscribe(subscribe.Subscription)))
                                        .With <FanIn.OnNext>(next =>
            {
                var id = next.Id;
                if (IsMarked(id) && !IsPending(id))
                {
                    _markedPending++;
                }
                Pending(id, on: true);
                _receivedInput = true;
                _inputs[id].SubReceive.CurrentReceive(new Actors.OnNext(next.Element));
            })
                                        .With <FanIn.OnComplete>(complete =>
            {
                var id = complete.Id;
                if (!IsPending(id))
                {
                    if (IsMarked(id) && !IsDepleted(id))
                    {
                        _markedDepleted++;
                    }
                    Depleted(id, on: true);
                    OnDepleted(id);
                }

                RegisterCompleted(id);
                _inputs[id].SubReceive.CurrentReceive(Actors.OnComplete.Instance);

                if (!_receivedInput && IsAllCompleted)
                {
                    OnCompleteWhenNoInput();
                }
            })
                                        .With <FanIn.OnError>(error => OnError(error.Id, error.Cause))
                                        .WasHandled);
        }
Пример #3
0
 protected bool WaitingExposedPublisher(object message)
 {
     if (message is ExposedPublisher)
     {
         ExposedPublisher = ((ExposedPublisher)message).Publisher;
         SubReceive.Become(DownstreamRunning);
         return(true);
     }
     throw new IllegalStateException(
               $"The first message must be [{typeof (ExposedPublisher)}] but was [{message}]");
 }
Пример #4
0
        protected virtual void OnSubscribe(ISubscription subscription)
        {
            if (subscription == null)
            {
                throw new ArgumentException("OnSubscribe require subscription not to be null");
            }

            if (_isUpstreamCompleted)
            {
                subscription.Cancel();
            }
            else
            {
                _upstream = subscription;
                // prefetch
                _upstream.Request(_inputBuffer.Length);
                SubReceive.Become(UpstreamRunning);
            }

            Pump.GotUpstreamSubscription();
        }
Пример #5
0
        /// <summary>
        /// TBD
        /// </summary>
        /// <param name="maxBufferSize">TBD</param>
        /// <param name="initialBufferSize">TBD</param>
        /// <param name="self">TBD</param>
        /// <param name="pump">TBD</param>
        /// <param name="afterShutdown">TBD</param>
        /// <exception cref="IllegalStateException">
        /// This exception is thrown when the first message isn't of type <see cref="ExposedPublisher"/>.
        /// </exception>
        public FanoutOutputs(int maxBufferSize, int initialBufferSize, IActorRef self, IPump pump, Action afterShutdown = null)
        {
            _self               = self;
            _pump               = pump;
            _afterShutdown      = afterShutdown;
            MaxBufferSize       = maxBufferSize;
            InitialBufferSize   = initialBufferSize;
            NeedsDemand         = DefaultOutputTransferStates.NeedsDemand(this);
            NeedsDemandOrCancel = DefaultOutputTransferStates.NeedsDemandOrCancel(this);
            SubReceive          = new SubReceive(message =>
            {
                if (!(message is ExposedPublisher publisher))
                {
                    throw new IllegalStateException($"The first message must be ExposedPublisher but was {message}");
                }

                ExposedPublisher = publisher.Publisher;
                SubReceive.Become(DownstreamRunning);
                return(true);
            });
        }
Пример #6
0
        protected BatchingInputBuffer(int count, IPump pump)
        {
            if (count <= 0)
            {
                throw new ArgumentException("Buffer Count must be > 0");
            }
            if ((count & (count - 1)) != 0)
            {
                throw new ArgumentException("Buffer Count must be power of two");
            }
            // TODO: buffer and batch sizing heuristics

            Count = count;
            Pump  = pump;

            _indexMask      = count - 1;
            _inputBuffer    = new object[count];
            _batchRemaining = RequestBatchSize;
            SubReceive      = new SubReceive(WaitingForUpstream);

            NeedsInput           = DefaultInputTransferStates.NeedsInput(this);
            NeedsInputOrComplete = DefaultInputTransferStates.NeedsInputOrComplete(this);
        }
Пример #7
0
 protected virtual void OnError(Exception e)
 {
     _isUpstreamCompleted = true;
     SubReceive.Become(Completed);
     InputOnError(e);
 }
Пример #8
0
 protected virtual void OnComplete()
 {
     _isUpstreamCompleted = true;
     SubReceive.Become(Completed);
     Pump.Pump();
 }
Пример #9
0
        /// <summary>
        /// TBD
        /// </summary>
        /// <param name="outputCount">TBD</param>
        /// <param name="impl">TBD</param>
        /// <param name="pump">TBD</param>
        public OutputBunch(int outputCount, IActorRef impl, IPump pump)
        {
            _outputCount = outputCount;
            _outputs     = new FanoutOutputs[outputCount];
            for (var i = 0; i < outputCount; i++)
            {
                _outputs[i] = new FanoutOutputs(i, impl, pump);
            }

            _marked    = new bool[outputCount];
            _pending   = new bool[outputCount];
            _cancelled = new bool[outputCount];
            _completed = new bool[outputCount];
            _errored   = new bool[outputCount];

            AllOfMarkedOutputs = new LambdaTransferState(
                isCompleted: () => _markedCanceled > 0 || _markedCount == 0,
                isReady: () => _markedPending == _markedCount);

            AnyOfMarkedOutputs = new LambdaTransferState(
                isCompleted: () => _markedCanceled == _markedCount,
                isReady: () => _markedPending > 0);

            // FIXME: Eliminate re-wraps
            SubReceive = new SubReceive(message => message.Match()
                                        .With <FanOut.ExposedPublishers <T> >(exposed =>
            {
                var publishers = exposed.Publishers.GetEnumerator();
                var outputs    = _outputs.AsEnumerable().GetEnumerator();

                while (publishers.MoveNext() && outputs.MoveNext())
                {
                    outputs.Current.SubReceive.CurrentReceive(new ExposedPublisher(publishers.Current));
                }
            })
                                        .With <FanOut.SubstreamRequestMore>(more =>
            {
                if (more.Demand < 1)
                {
                    // According to Reactive Streams Spec 3.9, with non-positive demand must yield onError
                    Error(more.Id, ReactiveStreamsCompliance.NumberOfElementsInRequestMustBePositiveException);
                }
                else
                {
                    if (_marked[more.Id] && !_pending[more.Id])
                    {
                        _markedPending += 1;
                    }
                    _pending[more.Id] = true;
                    _outputs[more.Id].SubReceive.CurrentReceive(new RequestMore(null, more.Demand));
                }
            })
                                        .With <FanOut.SubstreamCancel>(cancel =>
            {
                if (_unmarkCancelled)
                {
                    UnmarkOutput(cancel.Id);
                }

                if (_marked[cancel.Id] && !_cancelled[cancel.Id])
                {
                    _markedCanceled += 1;
                }

                _cancelled[cancel.Id] = true;
                OnCancel(cancel.Id);
                _outputs[cancel.Id].SubReceive.CurrentReceive(new Cancel(null));
            })
                                        .With <FanOut.SubstreamSubscribePending>(pending => _outputs[pending.Id].SubReceive.CurrentReceive(SubscribePending.Instance))
                                        .WasHandled);
        }