SleepyQueue

I discovered in my Curse of the Azure Bonds port that I was handling system interrupts related to keyboard input incorrectly. What I needed was a blocking getKey function when keys were buffered. So I wrote some code to solve this using lock and a semaphore. Today I rewrote it into a generic class. Here it is:

public class SleepyQueue
{
  Queue queue;
  Semaphore semaphore;

  public SleepyQueue()
  {
    queue = new Queue();
    semaphore = new Semaphore(0, 1);
  }

  public void Enqueue(T t)
  {
    lock (queue)
    {
      queue.Enqueue(t);
      if (queue.Count == 1)
      {
        semaphore.Release();
      }
    }
  }

  public T Dequeue()
  {
    T item;
    semaphore.WaitOne();
    lock (queue)
    {
      item = queue.Dequeue();
      if (queue.Count > 0)
      {
        semaphore.Release();
      }
    }

    return item;
  }
}

This can be used like so

static void Main(string[] args)
{
  SleepyQueue<int> q = new SleepyQueue<int>();

  q.Enqueue(1);
  q.Enqueue(2);
  q.Enqueue(3);

  Timer t = new Timer(CallBack, q, 3000, 3000);

  while (true)
  {
    Console.WriteLine(q.Dequeue());
  }
}

static void CallBack(object state)
{
  SleepyQueue<int> q = (SleepyQueue<int>)state;
  q.Enqueue(System.DateTime.UtcNow.Second);
}

Then this morning our new developer was asking how to use IEnumerable<> to loops across a queue of objects, and it was the same lock/semaphore type problem.

I started modifying my generic class so I could post the code, but it got nasty quite quickly, so I’ll just pass for now, and work on getting our code correct…