Коллеги, возникло непреодолимое желание поделиться своим велосипедом, получить комментарии, может кому пригодится
Готового на .нет не нашел, вот сделал свое, с пятой попытки.
Основная задача, была сделать tread-safe пул буферов для сервера, первоначально реализовал это дело через lock, скорость работы lock подхода вынудила копать дальше, в сторону Interlocked, потом узал что правильно такой подход называется lock-free, а так же, что часто возникающая проблема в таких алгоритмах называется ABA (я с ней столкнулся в 3-4 попытке).
В процессе работы над пулом и появился ниже приведенный Stack. В последствии, находил ссылки на pdf-ы с алгоритмами LIFO, FIFO, но не разбирался, вероятно там тоже самое. Читал про .нет 4.0, но там, по описанию, алгоритмы основаны на SpinLock, так что возможно мое будет чуть быстрее
(хотя и со своими ограничениями)
class SafeStackItem<T>
{
public T Value;
public volatile Int32 Next;
}
class SafeStack<T>
where T : class
{
private volatile Int32 head;
private volatile Int32 count;
private SafeStackItem<T>[] array;
public SafeStack(SafeStackItem<T>[] array, int pushFrom, int pushCount)
{
this.head = -1;
this.array = array;
count = pushCount;
head = pushFrom;
for (int i = 0; i < pushCount - 1; i++)
array[i + pushFrom].Next = pushFrom + i + 1;
array[pushFrom + pushCount - 1].Next = -1;
}
#pragma warning disable 0420
public Int32 Pop()
{
while (count > 1)
{
Int32 head1 = head;
Int32 next1 = Interlocked.Exchange(ref array[head1].Next, -1);
if (next1 >= 0)
{
if (Interlocked.CompareExchange(ref head, next1, head1) == head1)
{
Interlocked.Decrement(ref count);
return head1;
}
else
Interlocked.Exchange(ref array[head1].Next, next1);
}
}
return -1;
}
public void Push(Int32 index)
{
Int32 head1, head2;
do
{
head1 = head;
array[index].Next = head1;
head2 = Interlocked.CompareExchange(ref head, index, head1);
} while (head1 != head2);
Interlocked.Increment(ref count);
}
#pragma warning restore 0420
}