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…