Здравствуйте, Jolly Roger, Вы писали:
JR>Набравшись наглости, рискну обратиться с просьбой — Вы не могли бы раскритиковать ещё один пример
Вроде выглядит нормально. Это классический стек, про который известно, что он работает... если тут, конечно, нет никаких глупых опечаток, но вроде я не вижу.
Единственное, вызовы Thread.MemoryBarrier() излишни, но очень дороги. Их надо убрать.
Плюс, я бы убрал переменную count, т.к. пользы от неё обычно мало, а стоимость Push/Pop она удваивает. Кстати, она тут может возвращать -1, что может быть весьма удивительно для вызывающего кода. Если она *действительно* нужна, то я бы перенёс Interlocked.Increment(ref count) в начало метода — обычно лучше вернуть на 1 больше, чем на 1 меньше.
Если уж совсем придираться, то лучше использовать возвращаемое значение из CompareExchange(), т.к. это гарантированно актуальное значение, а дополнительное перечитывание разделяемой переменной может вносить негативный эффект при большой нагрузке.
Но это всё исключительно по производительности, а не по корректности.
В итоге получается что-то типа такого, я думаю это должно работать видимо пошустрее на синтетическом тесте:
public T Pop()
{
StackItem<T> tmpHead = Head;
StackItem<T> tmpHead2;
for (;;)
{
if (tmpHead == null)
return null;
tmpHead2 = Interlocked.CompareExchange<StackItem<T>>(ref Head, tmpHead.Next, tmpHead);
if (tmpHead2 == tmpHead)
return tmpHead.Value;
tmpHead = tmpHead2;
}
}
public void Push(T data)
{
StackItem<T> item = new StackItem<T>(data);
StackItem<T> tmpHead = Head;
StackItem<T> tmpHead2;
for (;;)
{
item.Next = tmpHead;
tmpHead2 = Interlocked.CompareExchange<StackItem<T>>(ref Head, item, tmpHead);
if (tmpHead2 == tmpHead)
return;
tmpHead = tmpHead2;
}
}
}