Skip to content

Instantly share code, notes, and snippets.

@jcmoore
Last active February 7, 2017 08:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jcmoore/2ccb56e53f6d9b6dbd674aed82535908 to your computer and use it in GitHub Desktop.
Save jcmoore/2ccb56e53f6d9b6dbd674aed82535908 to your computer and use it in GitHub Desktop.
DoubleSpaceQueue: a simple FIFO queue built on top of two re-sizable ring buffers (should only use up to 2*MaxSize -- "double" -- space)
function DoubleSpaceQueue () {
this._upperBack = 0;
this._upperFront = 0;
this._lowerBack = 0;
this._lowerFront = 0;
this._back = [];
this._front = [];
}
DoubleSpaceQueue.prototype._transpose = function () {
var queue = this;
var index = 0;
var side = queue._back;
queue._back = queue._front;
queue._front = side;
index = queue._upperBack;
queue._upperBack = queue._upperFront;
queue._upperFront = index;
index = queue._lowerBack;
queue._lowerBack = queue._lowerFront;
queue._lowerFront = index;
};
DoubleSpaceQueue.prototype.enqueue = function (value) {
if (this._lowerFront > this._upperFront - 1) {
this._lowerFront = 0;
this._upperFront = 0;
// could shed excess capacity here // this._front = [];
this._transpose();
}
this._back[this._upperBack++] = value;
return this;
};
DoubleSpaceQueue.prototype.dequeue = function (sentinel) {
var value;
if (this._lowerFront < this._upperFront) {
value = this._front[this._lowerFront];
this._front[this._lowerFront++] = null;
return value;
} else if (this._lowerBack < this._upperBack) {
value = this._back[this._lowerBack];
this._back[this._lowerBack++] = null;
return value;
} else return sentinel;
};
DoubleSpaceQueue.prototype.peek = function (index, sentinel) {
var at = 0|index;
var back = this._upperBack - this._lowerBack;
var front = this._upperFront - this._lowerFront;
if (at < 0) return sentinel;
else if (front > at) return this._front[this._lowerFront + at];
else if (back > (at -= front > 0 ? front : 0)) return this._back[this._lowerBack + at];
else return sentinel;
};
DoubleSpaceQueue.prototype.end = function (sentinel) {
//return this.peek(this.size() - 1, sentinel);
return this._upperBack > this._lowerBack ?
this._back[this._upperBack - 1] : this._upperFront > this._lowerFront ?
this._front[this._upperFront - 1] : sentinel;
};
DoubleSpaceQueue.prototype.size = function () {
var back = this._upperBack - this._lowerBack;
var front = this._upperFront - this._lowerFront;
return (back > 0 ? back : 0) + (front > 0 ? front : 0);
};
function swiftCheck (instructions) {
var list = [];
var dsq = new DoubleSpaceQueue();
var count = 0|((1 + Math.random()) * ((0|instructions) || 100));
var value = 0;
var result = list;
while (count-- > 0) {
if (Math.random() < 0.5) {
if (Math.random() < 0.5) {
value = 0|(Math.random() * list.length);
if (list[value] !== dsq.peek(value)) throw new Error("index mismatch");
else if (list[list.length - 1] !== dsq.end()) throw new Error("freshest mismatch");
} else if (list.length !== dsq.size()) throw new Error("size mismatch");
} else if (Math.random() < 0.5) {
value = Math.random();
list.push(value);
dsq.enqueue(value);
} else if (list.shift() !== dsq.dequeue()) throw new Error("next mismatch");
}
result = list.slice();
if (list.length !== dsq.size()) throw new Error("total mismatch");
else while (list.length) if (list.shift() !== dsq.dequeue()) throw new Error("alignment mismatch");
return result;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment