/// <summary> /// Initializes a new instance of the <see cref="SignalSample{T}" /> class. /// </summary> /// <param name="unitOfOutput"> /// The discrete unit of output that was read from the channel's output stream. /// </param> /// <param name="lookBehindRange"> /// A range of discrete units of output preceding <paramref name="unitOfOutput" /> in the channel's output stream, or an /// empty range if look-behind was not requested. /// </param> /// <param name="lookAheadRange"> /// A range of discrete units of output following <paramref name="unitOfOutput" /> in the channel's output stream, or an /// empty range if look-ahead was not requested. /// </param> /// <exception cref="ArgumentNullException"> /// <paramref name="unitOfOutput" /> is <see langword="null" /> -or- <paramref name="lookAheadRange" /> is /// <see langword="null" /> -or- <paramref name="lookBehindRange" /> is <see langword="null" />. /// </exception> public SignalSample(DiscreteUnitOfOutput <T> unitOfOutput, OutputRange <T> lookBehindRange, OutputRange <T> lookAheadRange) { UnitOfOutput = unitOfOutput.RejectIf().IsNull(nameof(unitOfOutput)); LookAheadRange = lookAheadRange.RejectIf().IsNull(nameof(lookAheadRange)); LookBehindRange = lookBehindRange.RejectIf().IsNull(nameof(lookBehindRange)); }
/// <summary> /// Initializes a new instance of the <see cref="SignalSample{T}" /> class. /// </summary> /// <param name="unitOfOutput"> /// The discrete unit of output that was read from the channel's output stream. /// </param> /// <exception cref="ArgumentNullException"> /// <paramref name="unitOfOutput" /> is <see langword="null" />. /// </exception> public SignalSample(DiscreteUnitOfOutput <T> unitOfOutput) : this(unitOfOutput, new OutputRange <T>()) { return; }
/// <summary> /// Initializes a new instance of the <see cref="SignalSample{T}" /> class. /// </summary> /// <param name="unitOfOutput"> /// The discrete unit of output that was read from the channel's output stream. /// </param> /// <param name="lookBehindRange"> /// A range of discrete units of output preceding <paramref name="unitOfOutput" /> in the channel's output stream, or an /// empty range if look-behind was not requested. /// </param> /// <exception cref="ArgumentNullException"> /// <paramref name="unitOfOutput" /> is <see langword="null" /> -or- <paramref name="lookBehindRange" /> is /// <see langword="null" />. /// </exception> public SignalSample(DiscreteUnitOfOutput <T> unitOfOutput, OutputRange <T> lookBehindRange) : this(unitOfOutput, lookBehindRange, new OutputRange <T>()) { return; }
/// <summary> /// Asynchronously reads a sample from the channel's output stream at the specified index. /// </summary> /// <param name="index"> /// A zero-based index within the output stream at which to read. /// </param> /// <param name="lookBehindLength"> /// The number of discrete units of output preceding the specified index to include with the sample. The default value is /// zero. /// </param> /// <param name="lookAheadLength"> /// The number of discrete units of output following the specified index to include with the sample. The default value is /// zero. /// </param> /// <returns> /// A task representing the asynchronous operation and containing a sample from the channel's output stream at the specified /// index. /// </returns> /// <exception cref="ArgumentOutOfRangeException"> /// <see cref="InvalidReadBehavior" /> is equal to <see cref="InvalidReadBehavior.RaiseException" /> and /// <paramref name="index" /> is less than zero -or- <paramref name="lookBehindLength" /> is less than zero -or- /// <paramref name="lookAheadLength" /> is less than zero -or- the resulting sample range precedes the start boundary of the /// channel's output stream -or- the resulting sample range exceeds the end boundary of the channel's output stream. /// </exception> /// <exception cref="ChannelReadException"> /// An exception was raised while performing the read operation, or the channel was unavailable. /// </exception> public Task <SignalSample <T> > ReadAsync(Int32 index, Int32 lookBehindLength, Int32 lookAheadLength) { switch (Status) { case ChannelStatus.Live: break; case ChannelStatus.Silent: return(Task.FromResult(new SignalSample <T>(ReadSilence(index)))); case ChannelStatus.Unavailable: throw new ChannelReadException(this); default: throw new InvalidOperationException($"The specified channel status, {Status}, is not supported."); } if (OutputLengthIsFixed) { var argumentOutOfRangeExceptionParameterName = (String)null; if (index < 0 || index >= OutputLength) { argumentOutOfRangeExceptionParameterName = nameof(index); } else if (lookBehindLength < 0 || lookBehindLength > index) { argumentOutOfRangeExceptionParameterName = nameof(lookBehindLength); } else if (lookAheadLength < 0 || lookAheadLength >= (OutputLength - index)) { argumentOutOfRangeExceptionParameterName = nameof(lookAheadLength); } if (argumentOutOfRangeExceptionParameterName is null == false) { switch (InvalidReadBehavior) { case InvalidReadBehavior.RaiseException: throw new ArgumentOutOfRangeException(argumentOutOfRangeExceptionParameterName); case InvalidReadBehavior.ReadSilence: return(Task.FromResult(new SignalSample <T>(ReadSilence(index)))); default: throw new InvalidOperationException($"The specified invalid read behavior, {InvalidReadBehavior}, is not supported."); } } } var startIndex = (index - lookBehindLength); var count = (lookBehindLength + lookAheadLength + 1); var endIndex = (startIndex + count); var range = default(T[]); using (var controlToken = StateControl.Enter()) { try { var outputRange = new T[count]; if (TryRead(startIndex, count, outputRange)) { range = outputRange; } else { Status = ChannelStatus.Unavailable; throw new ChannelReadException(this); } } catch (ChannelReadException) { Status = ChannelStatus.Unavailable; throw; } catch (Exception exception) { Status = ChannelStatus.Unavailable; throw new ChannelReadException(this, exception); } } var unitOfOutput = new DiscreteUnitOfOutput <T>(range[lookBehindLength], lookBehindLength); var lookBehindList = new List <DiscreteUnitOfOutput <T> >(lookBehindLength); var lookAheadList = new List <DiscreteUnitOfOutput <T> >(lookAheadLength); for (var i = 0; i < lookBehindLength; i++) { lookBehindList.Add(new DiscreteUnitOfOutput <T>(range[i], (startIndex + i))); } for (var i = 0; i < lookAheadLength; i++) { var adjustment = (lookBehindLength + i + 1); lookAheadList.Add(new DiscreteUnitOfOutput <T>(range[adjustment], (startIndex + adjustment))); } return(Task.FromResult(new SignalSample <T>(unitOfOutput, new OutputRange <T>(lookBehindList), new OutputRange <T>(lookAheadList)))); }