public int Drain(Action <T> act, int limit) { long consumerIndex; long pIndex; for (var i = 0; i < limit; i++) { do { pIndex = this.producerIndex.VolatileRead(); consumerIndex = this.consumerIndex.VolatileRead(); if (consumerIndex >= pIndex) { return(i); } } while (!buffer.HasValue(consumerIndex) || !this.consumerIndex.CompareExchange( consumerIndex + 1, consumerIndex)); var success = this.buffer.TryGet(consumerIndex, out T value); Debug.Assert(success, "Did not successfully get the value in a drain"); act(value); success = this.buffer.Clear(consumerIndex); Debug.Assert(success, "Unable to clear the value on a drain"); } return(limit); }
public bool TryPoll(out T value) { long pIndex; long consumerIndex; do { pIndex = this.producerIndex.VolatileRead(); consumerIndex = this.consumerIndex.VolatileRead(); if (consumerIndex >= pIndex) { value = default(T); return(false); } } while (!this.buffer.HasValue(consumerIndex) || !this.consumerIndex.CompareExchange(consumerIndex + 1, consumerIndex)); var get = this.buffer.TryGet(consumerIndex, out value); this.buffer.Clear(consumerIndex); Debug.Assert(get, $"Failed to get the value. {consumerIndex}"); return(true); }
public bool Offer(T value) { var capacity = this.buffer.Length; long pIndex; long consumerIndex; do { pIndex = this.producerIndex.VolatileRead(); consumerIndex = this.consumerIndex.VolatileRead(); if (pIndex - capacity >= consumerIndex) { return(false); } } while (!this.buffer.IsEmpty(pIndex) || // Need to go around again if a value is still at that position. !this.producerIndex.CompareExchange(pIndex + 1, pIndex)); var set = this.buffer.Set(pIndex, value); Debug.Assert(set, $"Did not find an open position correctly {pIndex}"); return(true); }