singrdk/base/Kernel/SingSharp.Runtime/TQueue.sg

121 lines
3.5 KiB
Plaintext

///////////////////////////////////////////////////////////////////////////////
//
// Microsoft Research Singularity
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// File: TQueue.sg
//
// Note: File is part of Sing# runtime files and copied into Singularity tree
// whenever a new version of Sing# is dropped.
//
using Microsoft.SingSharp;
namespace Microsoft.Singularity.Channels {
public class TQueue<T> : ITracked where T : ITracked {
private Node! listSentinel;
public TQueue() {
this.listSentinel = new Node();
base();
}
private class Node {
unsafe internal T data;
internal Node! next;
internal Node! prev;
internal Node() {
this.next = this;
this.prev = this;
}
internal Node([Claims] T! arg) {
this.next = this;
this.prev = this;
this.data = arg;
}
internal T Unlink() {
this.prev.next = this.next;
this.next.prev = this.prev;
this.next = this;
this.prev = this;
return this.data;
}
internal void LinkAsNext([Claims] T! data) {
Node next = new Node(data);
next.next = this.next;
this.next = next;
next.prev = this;
next.next.prev = next;
}
internal void LinkAsPrev([Claims] T! data) {
Node prev = new Node(data);
prev.prev = this.prev;
this.prev = prev;
prev.next = this;
prev.prev.next = prev;
}
}
#region ITracked members
void ITracked.Release() {}
void ITracked.Acquire() {}
public void Dispose()
{
Node current = this.listSentinel.next;
while (current != this.listSentinel) {
T! data = (!)current.data;
data.Dispose();
current = current.next;
}
this.listSentinel = new Node();
}
void ITracked.Expose() {}
void ITracked.UnExpose() {}
#endregion
public void AddHead([Claims] T! data) {
this.listSentinel.LinkAsNext(data);
}
public void AddTail([Claims] T! data) {
this.listSentinel.LinkAsPrev(data);
}
public bool Empty { get { return this.listSentinel.next == this.listSentinel; } }
public T ExtractHead() {
// Checking if list is empty
// and returning null causes the compiler to warn
// that return value can't be null (?).
//
// The following code works correctly whether the
// queue is empty or not.
Node candidate = this.listSentinel.next;
return candidate.Unlink();
}
public T ExtractTail() {
// Checking if list is empty
// and returning null causes the compiler to warn
// that return value can't be null (?).
//
// The following code works correctly whether the
// queue is empty or not.
Node candidate = this.listSentinel.prev;
return candidate.Unlink();
}
}
}