/////////////////////////////////////////////////////////////////////////////// // // 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 : 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(); } } }