-
-
Save Artur2/f46ff732161dcd35c7b7 to your computer and use it in GitHub Desktop.
Lock Free List Sample
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class LockFreeList<T> : IEnumerable<T> | |
{ | |
private volatile Node<T> _head; | |
private class Node<TItem> | |
{ | |
public Node<TItem> Next { get; set; } | |
public TItem Value { get; set; } | |
} | |
public void Add(T item) | |
{ | |
var spin = new SpinWait(); | |
var node = new Node<T>() { Value = item }; | |
var head = (Node<T>)null; | |
while (true) | |
{ | |
head = _head; | |
node.Next = head; | |
if (Interlocked.CompareExchange(ref _head, node, head) == head) | |
break; | |
spin.SpinOnce(); | |
} | |
} | |
public bool TryGet(out T item) | |
{ | |
item = default(T); | |
var spin = new SpinWait(); | |
var head = (Node<T>)null; | |
while (true) | |
{ | |
head = _head; | |
if (head == null) | |
return false; | |
if (Interlocked.CompareExchange(ref _head, head.Next, head) == head) | |
{ | |
item = head.Value; | |
return true; | |
} | |
spin.SpinOnce(); | |
} | |
} | |
public IEnumerator<T> GetEnumerator() | |
{ | |
return new LockFreeEnumerator(this); | |
} | |
IEnumerator IEnumerable.GetEnumerator() | |
{ | |
return new LockFreeEnumerator(this); | |
} | |
private class LockFreeEnumerator : IEnumerator<T> | |
{ | |
private LockFreeList<T> _lockFreeList; | |
private Node<T> _current; | |
private Node<T> _default; | |
public LockFreeEnumerator(LockFreeList<T> lockFreeList) | |
{ | |
_lockFreeList = lockFreeList; | |
_default = _lockFreeList._head; | |
} | |
public T Current | |
{ | |
get | |
{ | |
return _current.Value; | |
} | |
} | |
object IEnumerator.Current | |
{ | |
get | |
{ | |
return _current; | |
} | |
} | |
public void Dispose() | |
{ | |
} | |
public bool MoveNext() | |
{ | |
if (_current == null) | |
{ | |
Interlocked.Exchange(ref _current, _lockFreeList._head); | |
if (_current == null) | |
return false; | |
return true; | |
} | |
else | |
{ | |
Interlocked.Exchange(ref _current, _current.Next); | |
if (_current == null) | |
return false; | |
return true; | |
} | |
} | |
public void Reset() | |
{ | |
Interlocked.Exchange(ref _current, _default); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment