Skip to content

Instantly share code, notes, and snippets.

@jtwb
Created September 16, 2010 06:07
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jtwb/582040 to your computer and use it in GitHub Desktop.
Save jtwb/582040 to your computer and use it in GitHub Desktop.
/*
* WARNING
* This is just an idea. This code might not actually run. There are no
* tests. It was abandoned before I could finish it.
*/
/*
* AutoQueue
*
* www.github.com/jtwb
*
* Thread-safe queue which runs @operator every @frequency milliseconds
*
* God damn it, browser js engines don't actually interleave threads,
* so this is totally unnecessary.
*
* But I think the withLock(callback) approach is kind of a sexy alternative
* to the usual plan of polling for a mutex.
*
*
*
*/
/*
// example:
var queue = new AutoQueue(800, function(innerqueue) {
// operator is run by withLock
var queuestate = innerqueue.clearAll();
});
queue.withLock(
function(innerqueue) {
innerqueue.put('a');
innerqueue.put('b');
innerqueue.put('c');
}
);
queue.run();
*/
AutoQueue = function(frequency, operator) {
this.frequency = frequency;
this.operator = operator;
this.data = [];
this.lockQueue = [];
this.run();
};
/*
* Internal component for thread-safety
*/
AutoQueue.Lock = function() {
};
/*
* API class available within withLock callback
*/
AutoQueue.ClientApi = function(impl, lock) {
this.impl = impl;
this.lock = lock;
};
/*
* Push item on queue
*
* Thread-safe.
*/
AutoQueue.ClientApi.prototype.put = function(obj) {
if (this.impl.lock === this.lock) {
this.impl.data.push(obj);
}
};
/*
* Clear the queue
* and return all deleted items.
*
* Thread-safe.
*/
AutoQueue.ClientApi.prototype.clearAll = function() {
if (this.impl.lock === this.lock) {
var dataCopy = [];
for (i in this.impl.data) {
dataCopy[i] = this.impl.data[i];
}
this.impl.data = [];
return dataCopy;
}
};
/*
* Run 'callback' with exclusive access to the object
* No other class can modify the queue until callback returns
*/
AutoQueue.prototype.withLock = function(callback) {
/*
* If lockQueue isn't empty, run next one
*/
var nextWithLock = function() {
if (!this.lockQueue.length) return;
var next = this.lockQueue.shift();
return runWithLock(next);
};
var runWithLock = function(cb) {
this.lock = new AutoQueue.Lock();
var api = new AutoQueue.ClientApi(this, lock);
cb(api);
delete this.lock;
return nextWithLock();
};
if (!this.lock) {
runWithLock(callback);
} else {
this.lockQueue.push(callback);
}
};
AutoQueue.prototype.run = function() {
var processQueue = function() {
if (this.running) {
this.withLock(this.operator);
setTimeout(processQueue, this.frequency);
}
};
this.running = true;
processQueue();
};
AutoQueue.prototype.stop = function() {
this.running = false;
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment