public SimpleOutputs(IActorRef actor, IPump pump) { Actor = actor; Pump = pump; SubReceive = new SubReceive(WaitingExposedPublisher); NeedsDemand = DefaultOutputTransferStates.NeedsDemand(this); NeedsDemandOrCancel = DefaultOutputTransferStates.NeedsDemandOrCancel(this); }
/// <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); }
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}]"); }
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(); }
/// <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); }); }
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); }
protected virtual void OnError(Exception e) { _isUpstreamCompleted = true; SubReceive.Become(Completed); InputOnError(e); }
protected virtual void OnComplete() { _isUpstreamCompleted = true; SubReceive.Become(Completed); Pump.Pump(); }
/// <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); }