76 lines
2.2 KiB
C#
76 lines
2.2 KiB
C#
|
////////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Microsoft Research Singularity
|
||
|
//
|
||
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||
|
//
|
||
|
// File: ServiceRequestQueue.cs
|
||
|
//
|
||
|
// Note:
|
||
|
//
|
||
|
|
||
|
using System.Threading;
|
||
|
|
||
|
namespace Microsoft.Singularity
|
||
|
{
|
||
|
public class ServiceRequestQueue
|
||
|
{
|
||
|
// Invariant: head == null <==> tail == null
|
||
|
// tail.next is undefined.
|
||
|
private ServiceRequest head = null;
|
||
|
private ServiceRequest tail = null;
|
||
|
private SpinLock spinLock;
|
||
|
private AutoResetEvent enqueueEvent = new AutoResetEvent(false);
|
||
|
|
||
|
// Insert an element at the tail of the queue.
|
||
|
public void Enqueue(ServiceRequest req)
|
||
|
{
|
||
|
bool iflag = Processor.DisableInterrupts();
|
||
|
spinLock.Acquire();
|
||
|
try {
|
||
|
if (head == null) {
|
||
|
head = req;
|
||
|
tail = req;
|
||
|
}
|
||
|
else {
|
||
|
tail.next = req;
|
||
|
tail = req;
|
||
|
}
|
||
|
enqueueEvent.Set();
|
||
|
}
|
||
|
finally {
|
||
|
spinLock.Release();
|
||
|
Processor.RestoreInterrupts(iflag);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Block while the queue is empty, then return the head of the queue.
|
||
|
public ServiceRequest Dequeue()
|
||
|
{
|
||
|
while (true) {
|
||
|
bool iflag = Processor.DisableInterrupts();
|
||
|
spinLock.Acquire();
|
||
|
try {
|
||
|
if (tail != null)
|
||
|
{
|
||
|
ServiceRequest req = head;
|
||
|
if (req != tail) {
|
||
|
head = req.next;
|
||
|
}
|
||
|
else {
|
||
|
head = null;
|
||
|
tail = null;
|
||
|
}
|
||
|
return req;
|
||
|
}
|
||
|
}
|
||
|
finally {
|
||
|
spinLock.Release();
|
||
|
Processor.RestoreInterrupts(iflag);
|
||
|
}
|
||
|
enqueueEvent.WaitOne();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|