1

I found this helper class:

public sealed class QueuedLock
{
    private object innerLock;
    private volatile int ticketsCount = 0;
    private volatile int ticketToRide = 1;

    public QueuedLock()
    {
        innerLock = new Object();
    }

    public void Enter()
    {
        int myTicket = Interlocked.Increment(ref ticketsCount);
        Monitor.Enter(innerLock);
        while (true)
        {

            if (myTicket == ticketToRide)
            {
                return;
            }
            else
            {
                Monitor.Wait(innerLock);
            }
        }
    }

    public void Exit()
    {
        Interlocked.Increment(ref ticketToRide);
        Monitor.PulseAll(innerLock);
        Monitor.Exit(innerLock);
    }
}

here :

Is there a synchronization class that guarantee FIFO order in C#?

It works nice for me but I've just read some comments on this topic about the using of those volatile variables and I am not sure if there is an issue here or not. I understand the code and implemented it in my application in order to do the right job but I admit I can't see a negative impact with this approach in the future, at least, if there is one.

I haven't seen many ways of doing this so it would be nice to have a complete and safe version ready to be used in any situation.

So basically, the question is, can this approach be improved? Does it have any subtle issues?

Community
  • 1
  • 1
Olaru Mircea
  • 2,570
  • 26
  • 49

2 Answers2

4

For multithreaded FIFO (queue), .NET has provided ConcurrentQueue, I would recommend using ConcurrentQueue instead of using low level locks.

MSDN: ConcurrentQueue

Akash Kava
  • 39,066
  • 20
  • 121
  • 167
1

You can also review the TPL Dataflow BufferBlock class for this purpose:

// Hand-off through a BufferBlock<T>
private static BufferBlock<int> m_buffer = new BufferBlock<int>();

// Producer
private static void Producer()
{
    while(true)
    {
        int item = Produce();
        // storing the messages in FIFO queue
        m_buffer.Post(item);
    }
}

// Consumer
private static async Task Consumer()
{
    while(true)
    {
        int item = await m_buffer.ReceiveAsync();
        Process(item);
    }
}

// Main
public static void Main()
{
    var p = Task.Factory.StartNew(Producer);
    var c = Consumer();
    Task.WaitAll(p,c);
}
VMAtm
  • 27,943
  • 17
  • 79
  • 125