public void Enqueue(T item) { Node node = new Node(); node.Value = item; Node oldTail = null; Node oldNext = null; bool update = false; while (!update) { oldTail = tail; oldNext = oldTail.Next; // Did tail was already updated ? if (tail == oldTail) { if (oldNext == null) { // The place is for us update = Interlocked.CompareExchange(ref tail.Next, node, null) == null; } else { // another Thread already used the place so give him a hand by putting tail where it should be Interlocked.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 Interlocked.CompareExchange(ref tail, node, oldTail); Interlocked.Increment(ref count); }
bool InsertInternal(uint key, TKey subKey, T data, Func <T> dataCreator, out Node current) { Node node = new Node().Init(ComputeRegularKey(key), subKey, data); uint b = key % (uint)size; Node bucket; if ((bucket = GetBucket(b)) == null) { bucket = InitializeBucket(b); } if (!ListInsert(node, bucket, out current, dataCreator)) { return(false); } int csize = size; if (Interlocked.Increment(ref count) / csize > MaxLoad && (csize & 0x40000000) == 0) { Interlocked.CompareExchange(ref size, 2 * csize, csize); } current = node; return(true); }
public void EnterWriteLock() { SpinWait sw = new SpinWait(); do { int state = rwlock; if (state < RwWrite) { if (Interlocked.CompareExchange(ref rwlock, RwWrite, state) == state) { return; } state = rwlock; } // We register our interest in taking the Write lock (if upgradeable it's already done) while ((state & RwWait) == 0 && Interlocked.CompareExchange(ref rwlock, state | RwWait, state) != state) { state = rwlock; } // Before falling to sleep while (rwlock > RwWait) { sw.SpinOnce(); } } while (true); }
Node ListSearch(ulong key, TKey subKey, ref Node left, Node h) { Node leftNodeNext = null, rightNode = null; do { Node t = h; Node tNext = t.Next; do { if (!tNext.Marked) { left = t; leftNodeNext = tNext; } t = tNext.Marked ? tNext.Next : tNext; if (t == tail) { break; } tNext = t.Next; } while (tNext.Marked || t.Key < key || (tNext.Key == key && !comparer.Equals(subKey, t.SubKey))); rightNode = t; if (leftNodeNext == rightNode) { if (rightNode != tail && rightNode.Next.Marked) { continue; } else { return(rightNode); } } if (Interlocked.CompareExchange(ref left.Next, rightNode, leftNodeNext) == leftNodeNext) { if (rightNode != tail && rightNode.Next.Marked) { continue; } else { return(rightNode); } } } while (true); }
Node SetBucket(uint index, Node node) { try { slim.EnterReadLock(); CheckSegment(index, true); Interlocked.CompareExchange(ref buckets[index], node, null); return(buckets[index]); } finally { slim.ExitReadLock(); } }
public bool Delete(uint key, TKey subKey, out T data) { uint b = key % (uint)size; Node bucket; if ((bucket = GetBucket(b)) == null) { bucket = InitializeBucket(b); } if (!ListDelete(bucket, ComputeRegularKey(key), subKey, out data)) { return(false); } Interlocked.Decrement(ref count); return(true); }
public void EnterReadLock() { SpinWait sw = new SpinWait(); do { while ((rwlock & (RwWrite | RwWait)) > 0) { sw.SpinOnce(); } if ((Interlocked.Add(ref rwlock, RwRead) & (RwWait | RwWait)) == 0) { return; } Interlocked.Add(ref rwlock, -RwRead); } while (true); }
bool ListDelete(Node startPoint, ulong key, TKey subKey, out T data) { Node rightNode = null, rightNodeNext = null, leftNode = null; data = default(T); Node markedNode = null; do { rightNode = ListSearch(key, subKey, ref leftNode, startPoint); if (rightNode == tail || rightNode.Key != key || !comparer.Equals(subKey, rightNode.SubKey)) { return(false); } data = rightNode.Data; rightNodeNext = rightNode.Next; if (!rightNodeNext.Marked) { if (markedNode == null) { markedNode = new Node(); } markedNode.Init(rightNodeNext); if (Interlocked.CompareExchange(ref rightNode.Next, markedNode, rightNodeNext) == rightNodeNext) { break; } } } while (true); if (Interlocked.CompareExchange(ref leftNode.Next, rightNodeNext, rightNode) != rightNode) { ListSearch(rightNode.Key, subKey, ref leftNode, startPoint); } return(true); }
public bool TryDequeue(out T result) { result = default(T); bool advanced = false; while (!advanced) { Node oldHead = head; Node oldTail = tail; Node oldNext = oldHead.Next; if (oldHead == head) { // Empty case ? if (oldHead == oldTail) { // This should be false then if (oldNext != null) { // If not then the linked list is mal formed, update tail Interlocked.CompareExchange(ref tail, oldNext, oldTail); continue; } result = default(T); return(false); } else { result = oldNext.Value; advanced = Interlocked.CompareExchange(ref head, oldNext, oldHead) == oldHead; } } } Interlocked.Decrement(ref count); return(true); }
bool ListInsert(Node newNode, Node startPoint, out Node current, Func <T> dataCreator) { ulong key = newNode.Key; Node rightNode = null, leftNode = null; do { rightNode = current = ListSearch(key, newNode.SubKey, ref leftNode, startPoint); if (rightNode != tail && rightNode.Key == key && comparer.Equals(newNode.SubKey, rightNode.SubKey)) { return(false); } newNode.Next = rightNode; if (dataCreator != null) { newNode.Data = dataCreator(); } if (Interlocked.CompareExchange(ref leftNode.Next, newNode, rightNode) == rightNode) { return(true); } } while (true); }
public void ExitWriteLock() { Interlocked.Add(ref rwlock, -RwWrite); }
public void ExitReadLock() { Interlocked.Add(ref rwlock, -RwRead); }