0

I'm trying to figure out a way to thread safely and performance wise undo a TryDequeue on a ConcurrentQueue

My current solution to the problem is:

lock(_queue) {
    _queue = new ConcurrentQueue<IItem>(_queue.Reverse());
    _queue.Enqueue(item);
    _queue = new ConcurrentQueue<IItem>(_queue.Reverse());
}

But I don't know if this is the best way to do this, cause I'm locking it manually. But I need to be sure that the queue will not be altered in another thread during this process.

The reason for having to do this (I think) is that I do a TryPeek, do a check on the returned item, if it meets a criteria, I do a TryDequeue, and do the check again, if it fails the second time I want to do a rollback. Does this make sense?

Helder De Baere
  • 420
  • 1
  • 4
  • 19

1 Answers1

2

If you need to lock access to the queue while you read from it then the purpose of the ConcurrentQueue is negated. You might as well write your own wrapper around a normal Queue<T>.

public class UndoableQueue<T> // I shouldn't be allowed to name anything, ever.
{
    private readonly Queue<T> _queue = new Queue<T>();
    private readonly object _lock = new object();

    public void Enqueue(T item)
    {
        lock (_lock)
        {
            _queue.Enqueue(item);
        }
    }

    public bool TryDequeue(Func<T, bool> verify, out T dequeued)
    {
        lock (_lock)
        {
            if (!_queue.Any())
            {
                dequeued = default(T);
                return false;
            }
            if (verify(_queue.Peek()))
            {
                dequeued = _queue.Dequeue();
                return true;
            }
            dequeued = default(T);
            return false;
        }
    }
}

TryDequeue takes a function that determines whether or not to return the item. It works like TryDequeue on ConcurrentQueue except it returns a value if there's an item in the queue and the function returns true for that item.

Scott Hannen
  • 27,588
  • 3
  • 45
  • 62