public int TryPopRange(T[] items, int startIndex, int count) { RangeArgumentsCheck(items, startIndex, count); object temp; object end; do { temp = head; if (temp == null) { return(0); } end = temp; for (int j = 0; j < count; j++) { end = ((Node)end).Next; if (end == null) { break; } } } while (ClientInterlocked.CompareExchange(ref head, end, temp) != temp); int i; for (i = startIndex; i < startIndex + count && temp != null; i++) { items[i] = ((Node)temp).Value; end = temp; temp = ((Node)temp).Next; } ClientInterlocked.Add(ref this.count, -(i - startIndex)); return(i - startIndex); }
public void Enqueue(T item) { Node node = new Node(); node.Value = item; object oldTail = null; object oldNext = null; bool update = false; while (!update) { oldTail = tail; oldNext = ((Node)oldTail).Next; // Did tail was already updated ? if (tail == oldTail) { if (oldNext == null) { // The place is for us Node tailObj = (Node)tail; update = ClientInterlocked.CompareExchange(ref tailObj.Next, node, null) == null; } else { // another Thread already used the place so give him a hand by putting tail where it should be ClientInterlocked.CompareExchange(ref tail, oldNext, oldTail); } } } // At this point we added correctly our node, now we have to update tail. If it fails then it will be done by another thread ClientInterlocked.CompareExchange(ref tail, node, oldTail); ClientInterlocked.Increment(ref count); }