Example #1
0
            internal void InnerComplete(T value, bool hasValue)
            {
                if (hasValue)
                {
                    for (;;)
                    {
                        var sp = AddValue(value);

                        if (sp == null)
                        {
                            break;
                        }

                        try
                        {
                            value = reducer(sp.first, sp.second);
                        }
                        catch (Exception ex)
                        {
                            ExceptionHelper.ThrowIfFatal(ex);
                            InnerError(ex);
                            return;
                        }
                    }
                }

                if (Interlocked.Decrement(ref remaining) == 0)
                {
                    var sp = Volatile.Read(ref current);
                    current = null;
                    if (sp != null)
                    {
                        Complete(sp.first);
                    }
                    else
                    {
                        Complete();
                    }
                }
            }
Example #2
0
            SlotPair AddValue(T value)
            {
                for (;;)
                {
                    var c = Volatile.Read(ref current);

                    if (c == null)
                    {
                        c = new SlotPair();
                        if (Interlocked.CompareExchange(ref current, c, null) != null)
                        {
                            continue;
                        }
                    }

                    int slot = c.TryAcquireSlot();
                    if (slot < 0)
                    {
                        Interlocked.CompareExchange(ref current, null, c);
                        continue;
                    }
                    if (slot == 0)
                    {
                        c.first = value;
                    }
                    else
                    {
                        c.second = value;
                    }

                    if (c.ReleaseSlot())
                    {
                        Interlocked.CompareExchange(ref current, null, c);
                        return(c);
                    }
                    return(null);
                }
            }