今度こそ最後、汎用化バージョン(structでもOK) using System; using System.Threading;
public class CyclicBuffer<T> { private volatile int m_head; private volatile int m_tail; private readonly Entry[] m_buffer;
public CyclicBuffer(int capacity) { m_buffer = new Entry[capacity + 1]; }
public bool Enqueue(T value) { if (value == null) throw new ArgumentNullException("value"); int current; int next; do { current = m_head; next = current + 1 == m_buffer.Length ? 0 : current + 1; if (next == m_tail || m_buffer[current].Stored) return false; } while (Interlocked.CompareExchange(ref m_head, next, current) != current); m_buffer[current].Value = value; m_buffer[current].Stored = true; return true; }
public bool Dequeue(out T value) { int current; int next; do { current = m_tail; if (current == m_head || !m_buffer[current].Stored) { value = default(T); return false; } next = current + 1 == m_buffer.Length ? 0 : current + 1; } while (Interlocked.CompareExchange(ref m_tail, next, current) != current); value = m_buffer[current].Value; m_buffer[current].Value = default(T); m_buffer[current].Stored = false; return true; }
private struct Entry { public T Value; public volatile bool Stored; } }