public void EnterWriteLock() { SpinWait sw = new SpinWait(); do { int state = rwlock; if (state < RwWrite) { if (CustomInterlocked.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 && CustomInterlocked.CompareExchange(ref rwlock, state | RwWait, state) != state) { state = rwlock; } // Before falling to sleep while (rwlock > RwWait) { sw.SpinOnce(); } } while (true); }
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 = CustomInterlocked.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 CustomInterlocked.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 CustomInterlocked.CompareExchange(ref tail, node, oldTail); CustomInterlocked.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 (CustomInterlocked.Increment(ref count) / csize > MaxLoad && (csize & 0x40000000) == 0) { CustomInterlocked.CompareExchange(ref size, 2 * csize, csize); } current = node; return(true); }
bool ListPop(out T data) { Node rightNode = null, rightNodeNext = null, leftNode = head; data = default(T); do { rightNode = head.Next; if (rightNode == tail) { return(false); } data = rightNode.Data; rightNodeNext = rightNode.Next; if (!rightNodeNext.Marked) { if (CustomInterlocked.CompareExchange(ref rightNode.next, new Node(rightNodeNext), rightNodeNext) == rightNodeNext) { break; } } } while (true); if (CustomInterlocked.CompareExchange(ref leftNode.next, rightNodeNext, rightNode) != rightNodeNext) { ListSearch(rightNode.Key, ref leftNode); } return(true); }
public PopResult PopBottom(out T obj) { obj = default(T); int b = CustomInterlocked.Decrement(ref bottom); var a = array; int t = top; int size = b - t; if (size < 0) { // Set bottom to t CustomInterlocked.Add(ref bottom, t - b); return(PopResult.Empty); } obj = a.segment[b % a.size]; if (size > 0) { return(PopResult.Succeed); } CustomInterlocked.Add(ref bottom, t + 1 - b); if (CustomInterlocked.CompareExchange(ref top, t + 1, t) != t) { return(PopResult.Empty); } return(PopResult.Succeed); }
public bool CompareAndExchange(bool expected, bool newVal) { int newTemp = newVal ? Set : UnSet; int expectedTemp = expected ? Set : UnSet; return(CustomInterlocked.CompareExchange(ref flag, newTemp, expectedTemp) == expectedTemp); }
public void PushRange(T[] items, int startIndex, int count) { RangeArgumentsCheck(items, startIndex, count); Node insert = null; Node first = null; for (int i = startIndex; i < count; i++) { Node temp = new Node(); temp.Value = items[i]; temp.Next = insert; insert = temp; if (first == null) { first = temp; } } do { first.Next = Head; } while (CustomInterlocked.CompareExchange(ref head, insert, first.Next) != first.Next); CustomInterlocked.Add(ref this.count, count); }
public bool TryRemoveHash(int key, out T data) { if (ListDelete(key, out data)) { CustomInterlocked.Decrement(ref count); return(true); } return(false); }
public void Add(T item) { int index; CyclicDeque <T> bag = GetBag(out index); bag.PushBottom(item); staging.TryAdd(index, bag); AddHint(index); CustomInterlocked.Increment(ref count); }
public bool TryGetNextCompletion(out TCompletion continuation) { continuation = null; if (single != null && (continuation = (TCompletion)CustomInterlocked.Exchange(ref single, null)) != null) { return(true); } return(completed != null && Completed.TryPop(out continuation)); }
public void Push(T item) { Node temp = new Node(); temp.Value = item; do { temp.Next = Head; } while (CustomInterlocked.CompareExchange(ref head, temp, temp.Next) != temp.Next); CustomInterlocked.Increment(ref count); }
public void Add(TCompletion continuation) { if (single == null && CustomInterlocked.CompareExchange(ref single, continuation, null) == null) { return; } if (completed == null) { CustomInterlocked.CompareExchange(ref completed, new ConcurrentOrderedList <TCompletion> (), null); } Completed.TryAdd(continuation); }
void AddHint(int index) { // We only take thread index that can be stored in 5 bits (i.e. thread ids 1-15) if (index > 0xF) { return; } var hs = hints; // If cas failed then we don't retry CustomInterlocked.CompareExchange(ref hints, (int)(((uint)hs) << 4 | (uint)index), (int)hs); }
Node SetBucket(uint index, Node node) { try { slim.EnterReadLock(); CheckSegment(index, true); CustomInterlocked.CompareExchange(ref buckets[index], node, null); return((Node)buckets[index]); } finally { slim.ExitReadLock(); } }
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 (CustomInterlocked.CompareExchange(ref left.next, rightNode, leftNodeNext) == leftNodeNext) { if (rightNode != tail && rightNode.Next.Marked) { continue; } else { return(rightNode); } } } while (true); }
Node ListSearch(int key, ref Node left) { Node leftNodeNext = null, rightNode = null; do { Node t = head; 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); rightNode = t; if (leftNodeNext == rightNode) { if (rightNode != tail && rightNode.Next.Marked) { continue; } else { return(rightNode); } } if (CustomInterlocked.CompareExchange(ref left.next, rightNode, leftNodeNext) == leftNodeNext) { if (rightNode != tail && rightNode.Next.Marked) { continue; } else { return(rightNode); } } } while (true); }
public bool TryTake(out T result) { result = default(T); if (count == 0) { return(false); } int hintIndex; CyclicDeque <T> bag = GetBag(out hintIndex, false); bool ret = true; if (bag == null || bag.PopBottom(out result) != PopResult.Succeed) { var self = bag; ret = false; foreach (var other in staging) { // Try to retrieve something based on a hint ret = TryGetHint(out hintIndex) && (bag = container[hintIndex]).PopTop(out result) == PopResult.Succeed; // We fall back to testing our slot if (!ret && other.Value != self) { var status = other.Value.PopTop(out result); while (status == PopResult.Abort) { status = other.Value.PopTop(out result); } ret = status == PopResult.Succeed; hintIndex = other.Key; bag = other.Value; } // If we found something, stop if (ret) { break; } } } if (ret) { TidyBag(hintIndex, bag); CustomInterlocked.Decrement(ref count); } return(ret); }
public bool Remove(TCompletion continuation) { TCompletion temp = Single; if (temp != null && temp == continuation && CustomInterlocked.CompareExchange(ref single, null, continuation) == continuation) { return(true); } if (completed != null) { return(Completed.TryRemove(continuation)); } return(false); }
public bool TryAdd(T data) { Node node = new Node(); node.Data = data; node.Key = comparer.GetHashCode(data); if (ListInsert(node)) { CustomInterlocked.Increment(ref count); return(true); } return(false); }
public bool PeekBottom(out T obj) { obj = default(T); int b = CustomInterlocked.Decrement(ref bottom); var a = array; int t = top; int size = b - t; if (size < 0) { return(false); } obj = a.segment[b % a.size]; return(true); }
bool TryGetHint(out int index) { /* Funny little thing to know, since hints is signed (because CAS has no uint overload), * a shift-right operation is an arithmetic shift which might set high-order right bits * to 1 instead of 0 if the number turns negative. */ var hs = hints; index = 0; if (CustomInterlocked.CompareExchange(ref hints, (int)(((uint)hs) >> 4), hs) == hs) { index = (int)(hs & 0xF); } return(index > 0); }
public void Execute() { if (CustomInterlocked.Decrement(ref counter) != 0) { return; } owner.Status = TaskStatus.Running; bool canceled = false; List <Exception> exceptions = null; foreach (var task in tasks) { if (task.IsFaulted) { if (exceptions == null) { exceptions = new List <Exception> (); } exceptions.AddRange(task.Exception.InnerExceptions); continue; } if (task.IsCanceled) { canceled = true; } } if (exceptions != null) { owner.TrySetException(new AggregateException(exceptions), false, false); return; } if (canceled) { owner.CancelReal(); return; } owner.Finish(); }
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); } CustomInterlocked.Decrement(ref count); return(true); }
public override IList <IEnumerator <KeyValuePair <long, Tuple <long, long> > > > GetOrderablePartitions(int partitionCount) { if (partitionCount <= 0) { throw new ArgumentOutOfRangeException("partitionCount"); } long currentIndex = 0; Func <long> getNextIndex = () => CustomInterlocked.Increment(ref currentIndex) - 1; var enumerators = new IEnumerator <KeyValuePair <long, Tuple <long, long> > > [partitionCount]; for (int i = 0; i < partitionCount; i++) { enumerators[i] = GetEnumerator(getNextIndex); } return(enumerators); }
public void PushBottom(T obj) { int b = bottom; var a = array; // Take care of growing var size = b - top - upperBound; if (size > a.Size) { upperBound = top; a = a.Grow(b, upperBound); array = a; } // Register the new value a.segment[b % a.size] = obj; CustomInterlocked.Increment(ref bottom); }
public void EnterReadLock() { SpinWait sw = new SpinWait(); do { while ((rwlock & (RwWrite | RwWait)) > 0) { sw.SpinOnce(); } if ((CustomInterlocked.Add(ref rwlock, RwRead) & (RwWait | RwWait)) == 0) { return; } CustomInterlocked.Add(ref rwlock, -RwRead); } while (true); }
bool ListInsert(Node newNode) { int key = newNode.Key; Node rightNode = null, leftNode = null; do { rightNode = ListSearch(key, ref leftNode); if (rightNode != tail && rightNode.Key == key) { return(false); } newNode.next = rightNode; if (CustomInterlocked.CompareExchange(ref leftNode.next, newNode, rightNode) == rightNode) { return(true); } } while (true); }
public bool TryDequeue(out T result) { result = default(T); Node oldNext = null; bool advanced = false; while (!advanced) { Node oldHead = Head; Node oldTail = Tail; 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 CustomInterlocked.CompareExchange(ref tail, oldNext, oldTail); continue; } result = default(T); return(false); } else { result = oldNext.Value; advanced = CustomInterlocked.CompareExchange(ref head, oldNext, oldHead) == oldHead; } } } oldNext.Value = default(T); CustomInterlocked.Decrement(ref count); return(true); }
public bool TryPop(out T result) { Node temp; do { temp = Head; // The stak is empty if (temp == null) { result = default(T); return(false); } } while (CustomInterlocked.CompareExchange(ref head, temp.Next, temp) != temp); CustomInterlocked.Decrement(ref count); result = temp.Value; return(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 (CustomInterlocked.CompareExchange(ref rightNode.next, markedNode, rightNodeNext) == rightNodeNext) { break; } } } while (true); if (CustomInterlocked.CompareExchange(ref leftNode.next, rightNodeNext, rightNode) != rightNode) { ListSearch(rightNode.Key, subKey, ref leftNode, startPoint); } return(true); }