Example #1
0
            public void OnNext(TSource value)
            {
                TKey key;

                try
                {
                    key = _parent._keySelector(value);
                }
                catch (Exception exception)
                {
                    Error(exception);
                    return;
                }

                var fireNewMapEntry = false;
                ISubject <TElement> writer;

                try
                {
                    if (!_map.TryGetValue(key, out writer))
                    {
                        writer = new Subject <TElement>();
                        _map.Add(key, writer);
                        fireNewMapEntry = true;
                    }
                }
                catch (Exception exception)
                {
                    Error(exception);
                    return;
                }

                if (fireNewMapEntry)
                {
                    var group = new GroupedObservable <TKey, TElement>(key, writer, _parent._refCountDisposable);
                    _observer.OnNext(group);
                }

                TElement element;

                try
                {
                    element = _parent._elementSelector(value);
                }
                catch (Exception exception)
                {
                    Error(exception);
                    return;
                }

                writer.OnNext(element);
            }
Example #2
0
            public void OnNext(TSource value)
            {
                var key = this.keySelector(value);

                if (!this.groupedObservables.TryGetValue(key, out var groupedObservable))
                {
                    groupedObservable = new GroupedObservable(key);
                    this.groupedObservables.Add(key, groupedObservable);
                    this.observer.OnNext(groupedObservable);
                }

                groupedObservable.Subject.OnNext(value);
            }
 /// <summary>
 /// Projects each element of an observable sequence into the corresponding flow.
 /// <para/>
 /// This method implements the operator directly without the use of GroupBy. The performance is similar.
 /// </summary>
 /// <typeparam name="TFlowKey">The type of flow key.</typeparam>
 /// <typeparam name="TSource">The packet type.</typeparam>
 /// <param name="observable">The source sequence of packets.</param>
 /// <param name="getFlowKey">The function to get flow key from the element.</param>
 /// <returns>An observable sequence of flows.</returns>
 public static IObservable <IGroupedObservable <TFlowKey, TSource> > GroupFlowsDictionary <TFlowKey, TSource>(this IObservable <TSource> source, Func <TSource, TFlowKey> getFlowKey)
 {
     return(System.Reactive.Linq.Observable.Create <IGroupedObservable <TFlowKey, TSource> >(observer =>
     {
         var flowDictionary = new Dictionary <TFlowKey, GroupedObservable <TFlowKey, TSource> >();
         return source.Subscribe(value =>
         {
             var flowKey = getFlowKey(value);
             if (!flowDictionary.TryGetValue(flowKey, out var groupedObservable))
             {
                 groupedObservable = new GroupedObservable <TFlowKey, TSource>(flowKey);
                 flowDictionary.Add(flowKey, groupedObservable);
                 observer.OnNext(groupedObservable);
             }
             groupedObservable.OnNext(value);
         }, observer.OnError, () => { foreach (var c in flowDictionary)
                                      {
                                          c.Value.OnComplete();
                                      }
                                      observer.OnCompleted(); });
     }));
 }
Example #4
0
            public void OnNext(TSource value)
            {
                var key = default(TKey);

                try
                {
                    key = _parent._keySelector(value);
                }
                catch (Exception exception)
                {
                    Error(exception);
                    return;
                }

                var fireNewMapEntry = false;
                var writer          = default(ISubject <TElement>);

                try
                {
                    writer = _map.GetOrAdd(key, () => new Subject <TElement>(), out fireNewMapEntry);
                }
                catch (Exception exception)
                {
                    Error(exception);
                    return;
                }

                if (fireNewMapEntry)
                {
                    var group = new GroupedObservable <TKey, TElement>(key, writer, _parent._refCountDisposable);

                    var duration = default(IObservable <TDuration>);

                    var durationGroup = new GroupedObservable <TKey, TElement>(key, writer);
                    try
                    {
                        duration = _parent._durationSelector(durationGroup);
                    }
                    catch (Exception exception)
                    {
                        Error(exception);
                        return;
                    }

                    lock (base._observer)
                        base._observer.OnNext(group);

                    var md = new SingleAssignmentDisposable();
                    _parent._groupDisposable.Add(md);
                    md.Disposable = duration.SubscribeSafe(new δ(this, key, writer, md));
                }

                var element = default(TElement);

                try
                {
                    element = _parent._elementSelector(value);
                }
                catch (Exception exception)
                {
                    Error(exception);
                    return;
                }

                writer.OnNext(element);
            }
Example #5
0
            public override void OnNext(TSource value)
            {
                TKey key;

                try
                {
                    key = _keySelector(value);
                }
                catch (Exception exception)
                {
                    Error(exception);
                    return;
                }

                var fireNewMapEntry = false;
                ISubject <TElement> writer;

                try
                {
                    //
                    // Note: The box instruction in the IL will be erased by the JIT in case T is
                    //       a value type. In fact, the whole if block will go away and we'll end
                    //       up with nothing but the GetOrAdd call below.
                    //
                    //       See GroupBy for more information and confirmation of this fact using
                    //       the SOS debugger extension.
                    //
                    if (key == null)
                    {
                        lock (_nullGate)
                        {
                            if (_null == null)
                            {
                                _null           = NewSubject();
                                fireNewMapEntry = true;
                            }

                            writer = _null;
                        }
                    }
                    else
                    {
                        writer = _map.GetOrAdd(key, NewSubject, out fireNewMapEntry);
                    }
                }
                catch (Exception exception)
                {
                    Error(exception);
                    return;
                }

                if (fireNewMapEntry)
                {
                    var group = new GroupedObservable <TKey, TElement>(key, writer, _refCountDisposable);

                    var durationGroup = new GroupedObservable <TKey, TElement>(key, writer);

                    IObservable <TDuration> duration;
                    try
                    {
                        duration = _durationSelector(durationGroup);
                    }
                    catch (Exception exception)
                    {
                        Error(exception);
                        return;
                    }

                    lock (_gate)
                    {
                        ForwardOnNext(group);
                    }

                    var durationObserver = new DurationObserver(this, key, writer);
                    _groupDisposable.Add(durationObserver);
                    durationObserver.SetResource(duration.SubscribeSafe(durationObserver));
                }

                TElement element;

                try
                {
                    element = _elementSelector(value);
                }
                catch (Exception exception)
                {
                    Error(exception);
                    return;
                }

                //
                // ISSUE: Rx v1.x shipped without proper handling of the case where the duration
                //        sequence fires concurrently with the OnNext code path here. In such a
                //        case, the subject can be completed before we get a chance to send out
                //        a new element. However, a resurrected group for the same key won't get
                //        to see the element either. To guard against this case, we'd have to
                //        check whether the OnNext call below lost the race, and resurrect a new
                //        group if needed. Unfortunately, this complicates matters when the
                //        duration selector triggers synchronously (e.g. Return or Empty), which
                //        causes the group to terminate immediately. We should not get stuck in
                //        this case, repeatedly trying to resurrect a group that always ends
                //        before we can send the element into it. Also, users may expect this
                //        base case to mean no elements will ever be produced, so sending the
                //        element into the group before starting the duration sequence may not
                //        be a good idea either. For the time being, we'll leave this as-is and
                //        revisit the behavior for vNext. Nonetheless, we'll add synchronization
                //        to ensure no concurrent calls to the subject are made.
                //
                writer.OnNext(element);
            }
Example #6
0
            public override void OnNext(TSource value)
            {
                var key = default(TKey);

                try
                {
                    key = _keySelector(value);
                }
                catch (Exception exception)
                {
                    Error(exception);
                    return;
                }

                var fireNewMapEntry = false;
                var writer          = default(Subject <TElement>);

                try
                {
                    //
                    // Note: The box instruction in the IL will be erased by the JIT in case T is
                    //       a value type. In fact, the whole if block will go away and we'll end
                    //       up with nothing but the TryGetValue check below.
                    //
                    //       // var fireNewMapEntry = false;
                    //       C:\Projects\Rx\Rx\Experimental\Main\Source\Rx\System.Reactive.Linq\Reactive\Linq\Observable\GroupBy.cs @ 67:
                    //       000007fb`6d544b80 48c7452800000000 mov     qword ptr [rbp+28h],0
                    //
                    //       // var writer = default(ISubject<TElement>);
                    //       C:\Projects\Rx\Rx\Experimental\Main\Source\Rx\System.Reactive.Linq\Reactive\Linq\Observable\GroupBy.cs @ 66:
                    //       000007fb`6d544b88 c6453400        mov     byte ptr [rbp+34h],0
                    //
                    //       // if (!_map.TryGetValue(key, out writer))
                    //       C:\Projects\Rx\Rx\Experimental\Main\Source\Rx\System.Reactive.Linq\Reactive\Linq\Observable\GroupBy.cs @ 86:
                    //       000007fb`6d544b8c 488b4560        mov     rax,qword ptr [rbp+60h]
                    //       ...
                    //
                    if (key == null)
                    {
                        if (_null == null)
                        {
                            _null           = new Subject <TElement>();
                            fireNewMapEntry = true;
                        }

                        writer = _null;
                    }
                    else
                    {
                        if (!_map.TryGetValue(key, out writer))
                        {
                            writer = new Subject <TElement>();
                            _map.Add(key, writer);
                            fireNewMapEntry = true;
                        }
                    }
                }
                catch (Exception exception)
                {
                    Error(exception);
                    return;
                }

                if (fireNewMapEntry)
                {
                    var group = new GroupedObservable <TKey, TElement>(key, writer, _refCountDisposable);
                    ForwardOnNext(group);
                }

                var element = default(TElement);

                try
                {
                    element = _elementSelector(value);
                }
                catch (Exception exception)
                {
                    Error(exception);
                    return;
                }

                writer.OnNext(element);
            }
Example #7
0
            public override void OnNext(TSource value)
            {
                var key = default(TKey);

                try
                {
                    key = parent.keySelector(value);
                }
                catch (Exception exception)
                {
                    Error(exception);
                    return;
                }

                var fireNewMapEntry = false;
                var writer          = default(ISubject <TElement>);

                try
                {
                    if (key == null)
                    {
                        if (nullKeySubject == null)
                        {
                            nullKeySubject  = new Subject <TElement>();
                            fireNewMapEntry = true;
                        }

                        writer = nullKeySubject;
                    }
                    else
                    {
                        if (!map.TryGetValue(key, out writer))
                        {
                            writer = new Subject <TElement>();
                            map.Add(key, writer);
                            fireNewMapEntry = true;
                        }
                    }
                }
                catch (Exception exception)
                {
                    Error(exception);
                    return;
                }

                if (fireNewMapEntry)
                {
                    var group = new GroupedObservable <TKey, TElement>(key, writer, refCountDisposable);
                    observer.OnNext(group);
                }

                var element = default(TElement);

                try
                {
                    element = parent.elementSelector(value);
                }
                catch (Exception exception)
                {
                    Error(exception);
                    return;
                }

                writer.OnNext(element);
            }