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(); } } }
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); } }