public StreamEventArrayObservable( IStreamable <Empty, TPayload> source, Func <StreamEvent <TPayload>[]> generator, QueryContainer container, string identifier) { Contract.Requires(source != null); this.source = source; this.generator = generator; this.container = container; this.identifier = identifier; if (this.container != null) { this.container.RegisterEgressSite(this.identifier); } }
public PartitionedEndEdgeFreeOutputPipe(IStreamable <TKey, TPayload> stream, IStreamObserver <TKey, TPayload> observer) : base(stream, observer) { this.getPartitionKey = GetPartitionExtractor <TPartitionKey, TKey>(); this.pool = MemoryManager.GetMemoryPool <TKey, TPayload>(stream.Properties.IsColumnar); this.errorMessages = stream.ErrorMessages; var compoundEqualityExpr = EqualityComparerExtensions.GetCompoundEqualityComparerExpression <ActiveEvent, long, TKey, TPayload>( e => e.End, EqualityComparerExpression <long> .Default, e => e.Key, stream.Properties.KeyEqualityComparer, e => e.Payload, stream.Properties.PayloadEqualityComparer); var equals = compoundEqualityExpr.GetEqualsExpr().Compile(); var getHashCode = compoundEqualityExpr.GetGetHashCodeExpr().Compile(); var generator = compoundEqualityExpr.CreateFastDictionary2Generator <ActiveEvent, int>(1, equals, getHashCode, stream.Properties.QueryContainer); this.dictPool = new DataStructurePool <FastDictionary2 <ActiveEvent, int> >(() => generator.Invoke()); this.pool.Get(out this.output); this.output.Allocate(); }
public void DisjointUnionLowWatermarks() { const int leftKey = 1; const int rightKey = 2; var left = new Subject <PartitionedStreamEvent <int, int> >(); var right = new Subject <PartitionedStreamEvent <int, int> >(); var qc = new QueryContainer(); var leftInput = qc.RegisterInput(left); var rightInput = qc.RegisterInput(right); var actualOutput = new List <PartitionedStreamEvent <int, int> >(); var inputs = new IStreamable <PartitionKey <int>, int>[] { leftInput, rightInput }; var union = new MultiUnionStreamable <PartitionKey <int>, int>(inputs, guaranteedDisjoint: true); var egress = qc.RegisterOutput(union).ForEachAsync(o => actualOutput.Add(o)); var process = qc.Restore(); left.OnNext(PartitionedStreamEvent.CreatePoint(leftKey, 100, 1)); left.OnNext(PartitionedStreamEvent.CreateLowWatermark <int, int>(101)); right.OnNext(PartitionedStreamEvent.CreatePoint(rightKey, 100, 1)); right.OnNext(PartitionedStreamEvent.CreateLowWatermark <int, int>(110)); process.Flush(); left.OnNext(PartitionedStreamEvent.CreatePoint(leftKey, 101, 1)); right.OnNext(PartitionedStreamEvent.CreatePoint(rightKey, 110, 1)); process.Flush(); left.OnCompleted(); right.OnCompleted(); var expected = new PartitionedStreamEvent <int, int>[] { PartitionedStreamEvent.CreatePoint(leftKey, 100, 1), PartitionedStreamEvent.CreatePoint(rightKey, 100, 1), PartitionedStreamEvent.CreateLowWatermark <int, int>(101), PartitionedStreamEvent.CreatePoint(leftKey, 101, 1), PartitionedStreamEvent.CreatePoint(rightKey, 110, 1), PartitionedStreamEvent.CreateLowWatermark <int, int>(110), PartitionedStreamEvent.CreateLowWatermark <int, int>(StreamEvent.InfinitySyncTime), }; Assert.IsTrue(expected.SequenceEqual(actualOutput)); }
public PartitionedIntervalObservable( IStreamable <PartitionKey <TKey>, TPayload> source, Expression <Func <TKey, long, long, TPayload, TResult> > constructor, QueryContainer container, string identifier) { Contract.Requires(source != null); this.source = source; this.constructor = constructor; this.container = container; this.identifier = identifier; if (this.container != null) { this.container.RegisterEgressSite(this.identifier); } }
private void Save(IStreamable sender) { if (sender is IImage) { var saveFileDialog = new System.Windows.Forms.SaveFileDialog(); saveFileDialog.FileName = "*"; saveFileDialog.DefaultExt = "jpg"; saveFileDialog.ValidateNames = true; saveFileDialog.Filter = "Image File (.jpg)|*.jpg"; DialogResult result = saveFileDialog.ShowDialog(); if (!(result == DialogResult.OK)) // Test result. { return; } sender.Save(saveFileDialog.FileName); } else if (sender is IVideo || sender is ICamera) { if (videoWriter == null) { var saveFileDialog = new System.Windows.Forms.SaveFileDialog(); saveFileDialog.FileName = "*"; saveFileDialog.DefaultExt = "gyg"; saveFileDialog.ValidateNames = true; saveFileDialog.Filter = "Gygax Video (.gyg)|*.gyg"; DialogResult result = saveFileDialog.ShowDialog(); if (!(result == DialogResult.OK)) // Test result. { return; } videoWriter = new GygaxVideoWriter(saveFileDialog.FileName); videoWriter.Source = (IStreamable)sender; RecordingButton.Visibility = Visibility.Visible; StopRecordingButton.Visibility = Visibility.Visible; } } }
private List <IStreamable> ReceiveObjectList(IZetboxContext ctx, ZetboxStreamReader sr) { List <IStreamable> result = new List <IStreamable>(); var cont = sr.ReadBoolean(); while (cont) { var objType = sr.ReadSerializableType(); IStreamable obj = (IStreamable)ctx.Internals().CreateUnattached(_iftFactory(objType.GetSystemType())); obj.FromStream(sr); result.Add((IStreamable)obj); cont = sr.ReadBoolean(); } return(result); }
public StartEdgeObservable( IStreamable <Empty, TPayload> source, Expression <Func <long, TPayload, TResult> > constructor, QueryContainer container, string identifier) { Contract.Requires(source != null); this.source = source; this.constructor = constructor; this.container = container; this.identifier = identifier; if (this.container != null) { this.container.RegisterEgressSite(this.identifier); } }
public SprayGroupImportStreamable( IStreamable <TKey, TSpray> source, int totalBranches, bool multicast = false, IComparerExpression <TSpray> sprayComparer = null) : base(source.Properties.ToMulticore(true)) { Contract.Requires(source != null); this.totalBranches = totalBranches; this.Source = source; this.spraySortOrderComparer = sprayComparer; // source.Properties.PayloadComparer; this.IsColumnar = source.Properties.IsColumnar; this.multicast = multicast; this.observerClassId = Guid.NewGuid(); }
public GroupStreamable( IEqualityComparerExpression <TInnerKey> comparer, IStreamable <TOuterKey, TSource> source, Expression <Func <TSource, TInnerKey> > keySelector) : base(source.Properties.Group(keySelector)) { Contract.Requires(source != null); Contract.Requires(keySelector != null); Source = source; KeySelector = keySelector; if (Source.Properties.IsColumnar && !CanGenerateColumnar()) { properties = properties.ToRowBased(); Source = Source.ColumnToRow(); } }
private async Task Peer_OnMessage(BitcoinPeer s, IStreamable msg) { switch (msg) { case Addr a: { foreach (var ip in a.Ips) { var ep = new IPEndPoint(ip.Ip.MapToIPv6(), ip.Port); var epb = ep.ToByteArray(); if (!await db.SetContainsAsync("hs:nodes:good-nodes", epb) && !await db.SetContainsAsync("hs:nodes:bad-nodes", epb)) { QueueNewNode(ep); } } break; } case Ping a: { var pong = new Pong(); pong.Nonce = a.Nonce; await s.WriteMessage(pong); break; } case bitcoin_lib.P2P.Version a: { GotVersion = true; //send verack and log await SetNodeDetails(a); var va = new VerAck(); await s.WriteMessage(va); var ga = new GetAddr(); await s.WriteMessage(ga); break; } } }
/// <summary> /// /// </summary> public virtual int ExitInput() { // TODO #region Beta if (devices[deviceId] == this) { devices[deviceId] = null; } if (asVirtualController && m_VirtualController != null) { int hjId = GetVirtualControllerId(); if (hjId < 0) { Log.w("DeviceBase", "Invalid virtual controller id"); } else if (VirtualController.controllers[hjId] == m_VirtualController) { VirtualController.controllers[hjId] = null; } else { } } #endregion Beta // DeinitSensors(); // if (m_Stream == null) { return(-1); } else { m_Stream.Close(); m_Stream = null; } // Release the Library resource at last. Library.Exit(); return(0); }
public void CommunicationDevicePushTest() { byte[] sendBuf = new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; byte[] recvBuf = new byte[10]; Stream cd = new Regulus.Remote.Standalone.Stream(); IStreamable peer = cd as IStreamable; cd.Push(sendBuf, 0, sendBuf.Length); System.Threading.Tasks.Task <int> receiveResult1 = peer.Receive(recvBuf, 0, 4); System.Threading.Tasks.Task <int> receiveResult2 = peer.Receive(recvBuf, 4, 6); int receiveCount1 = receiveResult1.GetAwaiter().GetResult(); int receiveCount2 = receiveResult2.GetAwaiter().GetResult(); Assert.AreEqual(4, receiveCount1); Assert.AreEqual(6, receiveCount2); }
internal static IObservable <TResult> ToTemporalObservable <TPayload, TResult>( this IStreamable <Empty, TPayload> stream, Expression <Func <long, TPayload, TResult> > constructor, QueryContainer container, string identifier) { Invariant.IsNotNull(stream, nameof(stream)); if (stream is IFusibleStreamable <Empty, TPayload> f && f.CanFuseEgressObservable) { if (stream.Properties.IsStartEdgeOnly) { return(f.FuseEgressObservable(Expression.Lambda <Func <long, long, TPayload, Empty, TResult> >(constructor.Body, constructor.Parameters[0], Expression.Parameter(typeof(long)), constructor.Parameters[1], Expression.Parameter(typeof(Empty))), container, identifier)); } } return(new StartEdgeObservable <TPayload, TResult>(stream, constructor, container, identifier)); }
public ShufflecastStreamable( IStreamable <TInnerKey, TSource> source, int totalBranchesL2, Expression <Func <TInnerKey, int, TSource, int[]> > destinationSelector = null) : base(source.Properties) { Contract.Requires(source != null); Contract.Requires(totalBranchesL2 > 0); this.Source = source; this.totalBranchesL2 = totalBranchesL2; this.powerOf2 = ((totalBranchesL2 & (totalBranchesL2 - 1)) == 0); if (destinationSelector != null) { this.destinationSelectorCompiled = destinationSelector.Compile(); } }
public PartitionStreamable( IStreamable <Empty, TPayload> source, Expression <Func <TPayload, TPartitionKey> > keySelector, long partitionLag) : base(source.Properties.Partition(keySelector)) { Contract.Requires(source != null); Contract.Requires(keySelector != null); this.Source = source; this.KeySelector = keySelector; this.PartitionLag = partitionLag; if (source.Properties.IsColumnar) { // No current support for partitioned columnar this.properties = this.properties.ToRowBased(); this.Source = this.Source.ColumnToRow(); } }
/// <summary> /// Shard a streamable /// </summary> /// <typeparam name="TPayload">The event payload type</typeparam> /// <param name="source">The stream to shard</param> /// <param name="shardArity">The number of shards to create</param> /// <returns>A sharded stream across <paramref name="shardArity"/> shards</returns> public static IShardedStreamable <Empty, TPayload> Shard <TPayload>(this IStreamable <Empty, TPayload> source, int shardArity = -1) { if (shardArity == -1) { shardArity = Config.StreamScheduler.scheduler.MapArity; } var spray = new SprayGroupImportStreamable <Empty, TPayload>(source, shardArity, false, null); var streamables = new IStreamable <Empty, TPayload> [shardArity]; for (int i = 0; i < shardArity; i++) { streamables[i] = new PassthroughStreamable <Empty, TPayload>(spray); } return(new ShardedStreamable <Empty, TPayload>(streamables)); }
/// <summary> /// ConsecutivePairs with gap_tolerance /// </summary> /// <typeparam name="TKey">Key type</typeparam> /// <typeparam name="TPayload">Payload type</typeparam> /// <typeparam name="TResult">Result type</typeparam> /// <param name="stream">Input stream</param> /// <param name="resultSelector">Compose result tuple using matching input events</param> /// <param name="gap_tol">Gap tolerance</param> /// <param name="period">Period of input stream (default: 1)</param> /// <returns>Pattern result stream</returns> public static IStreamable <TKey, TResult> ConsecutivePairs <TKey, TPayload, TResult>( this IStreamable <TKey, TPayload> stream, Expression <Func <TPayload, TPayload, TResult> > resultSelector, long gap_tol, long period = 1) { var clippedStream = stream .AlterEventDuration((s, e) => e - s + gap_tol) .Multicast(xs => xs.ClipEventDuration(xs)) .AlterEventDuration((s, e) => (e - s > gap_tol) ? period : e - s) ; var result = clippedStream .Multicast(xs => xs .ShiftEventLifetime(1) .Join(xs.AlterEventDuration(1), resultSelector)); return(result); }
/// <summary> /// Re-distribute the data across shards /// </summary> /// <param name="newLocation">Assign an optional new location descriptor</param> /// <returns>A new sharded streamable with the new key type and values</returns> public IShardedStreamable <TKey, TPayload> ReDistribute(ILocationDescriptor newLocation = null) { int newShardArity = (newLocation != null && (int)newLocation.GetLocation() > 0) ? (int)newLocation.GetLocation() : this.Streamables.Length; var shuffleL1Results = new ShuffleSameKeyStreamable <TKey, TPayload, TKey> [this.Streamables.Length]; for (int i = 0; i < this.Streamables.Length; i++) { shuffleL1Results[i] = new ShuffleSameKeyStreamable <TKey, TPayload, TKey>(this.Streamables[i], newShardArity, i); } var shuffleResults = new IStreamable <TKey, TPayload> [newShardArity]; for (int i = 0; i < newShardArity; i++) { shuffleResults[i] = new MultiUnionStreamable <TKey, TPayload>(shuffleL1Results); } return(new ShardedStreamable <TKey, TPayload>(shuffleResults)); }
/// <summary> /// Normalize a signal using standard score. /// </summary> /// <param name="source">Input stream</param> /// <param name="window">Normalization window</param> /// <returns>Normalized signal</returns> public static IStreamable <Empty, Signal> Normalize( this IStreamable <Empty, Signal> source, long window ) { return(source .AttachAggregate( s => s.Select(e => e.val), w => w.JoinedAggregate( w.Average(e => e), w.StandardDeviation(e => e), (avg, std) => new { avg, std } ), (signal, agg) => new Signal(signal.ts, (float)((signal.val - agg.avg) / agg.std)), window, window, window - 1 ) ); }
private static void JoinPointsTest(bool fixedInterval = false) { var left = new Subject <StreamEvent <string> >(); var right = new Subject <StreamEvent <string> >(); var qc = new QueryContainer(); IStreamable <Empty, string> leftInput = qc.RegisterInput(left); IStreamable <Empty, string> rightInput = qc.RegisterInput(right); if (fixedInterval) { leftInput = leftInput.AlterEventDuration(1); rightInput = rightInput.AlterEventDuration(1); } var query = leftInput.Join( rightInput, l => (l != null ? l[0].ToString() : null), r => (r != null ? r[0].ToString() : null), (l, r) => $"{l},{r}"); var output = new List <StreamEvent <string> >(); qc.RegisterOutput(query).ForEachAsync(o => output.Add(o)); var process = qc.Restore(); // Should match and egress immediately left.OnNext(StreamEvent.CreatePoint(100, "A1")); right.OnNext(StreamEvent.CreatePoint(100, "A2")); process.Flush(); var expected = new StreamEvent <string>[] { StreamEvent.CreatePoint(100, "A1,A2"), }; Assert.IsTrue(expected.SequenceEqual(output)); output.Clear(); left.OnCompleted(); right.OnCompleted(); }
public static bool IsOrderSensitiveEquivalentTo <TPayload>(this IStreamable <Empty, TPayload> input, StreamEvent <TPayload>[] comparison) { Invariant.IsNotNull(input, "input"); Invariant.IsNotNull(comparison, "comparison"); var events = input.ToStreamEventArray(); // Reodrer stream events with the same timstamp var orderedEvents = (StreamEvent <TPayload>[])events.Clone(); int start = 0; while (start < events.Length) { int end = start + 1; while (end < events.Length && events[end].SyncTime == events[start].SyncTime && !events[start].IsPunctuation && !events[end].IsPunctuation) { end++; } var segment = new ArraySegment <StreamEvent <TPayload> >(events, start, end - start); segment.OrderBy(e => e.OtherTime).ThenBy(e => e.Payload).ToArray().CopyTo(orderedEvents, start); start = end; } // Reodrer stream events with the same timstamp var orderedComparison = (StreamEvent <TPayload>[])comparison.Clone(); start = 0; while (start < comparison.Length) { int end = start + 1; while (end < comparison.Length && comparison[end].SyncTime == comparison[start].SyncTime && !comparison[start].IsPunctuation && !comparison[end].IsPunctuation) { end++; } var segment = new ArraySegment <StreamEvent <TPayload> >(comparison, start, end - start); segment.OrderBy(e => e.OtherTime).ThenBy(e => e.Payload).ToArray().CopyTo(orderedComparison, start); start = end; } return(orderedEvents.SequenceEqual(orderedComparison)); }
/// <summary> /// Resample signal from one frequency to a different one. /// </summary> /// <param name="source">Input stream</param> /// <param name="iperiod">Period of input signal stream</param> /// <param name="operiod">Period of output signal stream</param> /// <param name="offset">Offset</param> /// <returns>Result (output) stream in the new signal frequency</returns> public static IStreamable <Empty, Signal> Resample( this IStreamable <Empty, Signal> source, long iperiod, long operiod, long offset = 0) { return(source .Multicast(s => s.ClipEventDuration(s)) .Multicast(s => s .ShiftEventLifetime(1) .Join(s .AlterEventDuration(1), (l, r) => new { st = l.ts, sv = l.val, et = r.ts, ev = r.val })) .AlterEventLifetime(t => t - iperiod, iperiod) .Chop(offset, operiod) .HoppingWindowLifetime(1, operiod) .AlterEventDuration(operiod) .Select((t, e) => new Signal(t, ((e.ev - e.sv) * (t - e.st) / (e.et - e.st) + e.sv))) ); }
protected void Initialize() { if (this.Left.Properties.IsColumnar && this.Right.Properties.IsColumnar) { if (!CanGenerateColumnar()) { this.properties = this.properties.ToRowBased(); this.Left = this.Left.ColumnToRow(); this.Right = this.Right.ColumnToRow(); } } else if (this.Left.Properties.IsColumnar) { this.Left = this.Left.ColumnToRow(); } else if (this.Right.Properties.IsColumnar) { this.Right = this.Right.ColumnToRow(); } }
internal static IObservable <StreamEvent <TPayload> > ToStreamEventObservable <TPayload>( this IStreamable <Empty, TPayload> stream, QueryContainer container, string identifier, ReshapingPolicy reshapingPolicy) { Invariant.IsNotNull(stream, nameof(stream)); if (stream is IFusibleStreamable <Empty, TPayload> f && f.CanFuseEgressObservable) { if (reshapingPolicy == ReshapingPolicy.None) { return(f.FuseEgressObservable((s, e, p, k) => new StreamEvent <TPayload>(s, e, p), container, identifier)); } } return((reshapingPolicy == ReshapingPolicy.None) ? new StreamEventObservable <TPayload>(stream, container, identifier) : new StreamEventObservable <TPayload>(stream.ToEndEdgeFreeStream(), container, identifier)); }
public async System.Threading.Tasks.Task CommunicationDevicePushTest() { byte[] sendBuf = new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; byte[] recvBuf = new byte[10]; Stream cd = new Regulus.Remote.Standalone.Stream(); IStreamable peer = cd as IStreamable; await cd.Push(sendBuf, 0, sendBuf.Length); int receiveCount1 = await peer.Receive(recvBuf, 0, 4); int receiveCount2 = await peer.Receive(recvBuf, 4, 5); int receiveCount3 = await peer.Receive(recvBuf, 9, 2); Assert.Equal(4, receiveCount1); Assert.Equal(5, receiveCount2); Assert.Equal(1, receiveCount3); }
internal static void ToTextStream <TKey, TPayload>(this IStreamable <TKey, TPayload> input, Stream textStream) { using (var sw = new StreamWriter(textStream)) { input .ToStreamMessageObservable() .SynchronousForEach(message => { var bv = message.bitvector.col; for (int i = 0; i < message.Count; i++) { if ((bv[i >> 6] & (1L << (i & 0x3f))) == 0) { sw.WriteLine("{0}\t{1}\t{2}\t{3}", message.vsync.col[i], message.vother.col[i], message.key.col[i], message[i]); } } message.Free(); }); } }
/// <summary> /// Broadcast operation on a sharded streamable /// </summary> /// <param name="newLocation">Assign an optional new location descriptor</param> /// <returns>A new sharded streamable post-broadcast</returns> public IShardedStreamable <TKey, TPayload> Broadcast(ILocationDescriptor newLocation = null) { int newShardArity = (newLocation != null && (int)newLocation.GetLocation() > 0) ? (int)newLocation.GetLocation() : this.Streamables.Length; var broadcastResults = new SprayGroupImportStreamable <TKey, TPayload> [this.Streamables.Length]; for (int i = 0; i < this.Streamables.Length; i++) { broadcastResults[i] = new SprayGroupImportStreamable <TKey, TPayload>(this.Streamables[i], newShardArity, true); } var unionResults = new IStreamable <TKey, TPayload> [newShardArity]; for (int i = 0; i < newShardArity; i++) { unionResults[i] = new MultiUnionStreamable <TKey, TPayload>(broadcastResults); } return(new ShardedStreamable <TKey, TPayload>(unionResults)); }
public static void Test() { IStreamable <Empty, SensorReading> inputStream = CreateStream(); const int threshold = 42; var crossedThreshold = inputStream.Multicast( input => { // Alter all events 1 sec in the future. var alteredForward = input.AlterEventLifetime(s => s + 1, 1); // Compare each event that occurs at input with the previous event. // Note that, this one works for strictly ordered, strictly (e.g 1 sec) regular streams. var filteredInputStream = input.Where(s => s.Value > threshold); var filteredAlteredStream = alteredForward.Where(s => s.Value < threshold); return(filteredInputStream.Join( filteredAlteredStream, (evt, prev) => new { evt.Time, Low = prev.Value, High = evt.Value })); }); crossedThreshold.ToStreamEventObservable().ForEachAsync(r => Console.WriteLine(r)).Wait(); }
/// <summary> /// Peak detection query. /// </summary> /// <param name="source">Input stream</param> /// <param name="period">Period of input stream</param> /// <param name="window">Mean window</param> /// <param name="factor">Scaling factor</param> /// <returns>Peaks in the signal stream</returns> public static IStreamable <Empty, Signal> Peaks( this IStreamable <Empty, Signal> source, long period, float factor, long window = 400 ) { return(source .AttachAggregate( s => s.Select(e => e.val), w => w.Average(e => e * factor), (signal, avg) => new { signal, avg }, 2 * window, 1, window ) .Where(e => e.signal.val > e.avg) .Select(e => e.signal) .StitchAggregate(w => w.TopK(e => e.val, 1)) .Select(e => e.First().Payload) .AlterEventDuration(period) ); }
/// <summary> /// Detect a pattern over the incoming stream. Takes augmented finite automaton (AFA) as input. Create AFA using the Regex.* API or direct AFA specification. /// </summary> /// <typeparam name="TKey">Key type</typeparam> /// <typeparam name="TPayload">Payload type</typeparam> /// <typeparam name="TRegister">Result type (output of matcher is the register at an accepting state of the AFA)</typeparam> /// <typeparam name="TAccumulator">Accumulator type</typeparam> /// <param name="source">Source stream</param> /// <param name="afa">AFA specification</param> /// <param name="maxDuration">Maximum duration (window) for the pattern</param> /// <param name="allowOverlappingInstances">States whether to allow more than one state machine instance to be in effect at a time</param> /// <param name="isDeterministic">States whether to consider the AFA as deterministic</param> /// <returns>A stream of the matched results</returns> public static IStreamable <TKey, TRegister> Detect <TKey, TPayload, TRegister, TAccumulator>( this IStreamable <TKey, TPayload> source, Afa <TPayload, TRegister, TAccumulator> afa, long maxDuration = 0, bool allowOverlappingInstances = true, bool isDeterministic = false) { Invariant.IsNotNull(source, nameof(source)); if (maxDuration == 0) { if (!(source.Properties.IsConstantDuration && (source.Properties.ConstantDurationLength != null))) { throw new Exception("Either specify a MaxDuration parameter or use an input stream that is windowed by a constant"); } maxDuration = source.Properties.ConstantDurationLength.Value; } afa.AllowOverlappingInstances = allowOverlappingInstances; afa.IsDeterministic = isDeterministic; return(new AfaStreamable <TKey, TPayload, TRegister, TAccumulator>(source, afa, maxDuration)); }