Last active
February 7, 2017 08:35
-
-
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)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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