Skip to content

Instantly share code, notes, and snippets.

@icodeforlove
Last active August 29, 2015 14:21
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 icodeforlove/deb0f19a9e7bd528bd48 to your computer and use it in GitHub Desktop.
Save icodeforlove/deb0f19a9e7bd528bd48 to your computer and use it in GitHub Desktop.
(function () {
function TaskWorker ($config) {
this.worker = this.createWorker();
this.worker.addEventListener('message', this.onWorkerMessage.bind(this));
this.tasks = [];
this.onTaskComplete = $config.onTaskComplete;
this.lastTaskTimestamp = null;
}
TaskWorker.prototype = {
functionToObjectURL: function (func) {
var blob,
stringFunc = func.toString();
stringFunc = stringFunc.substring(stringFunc.indexOf('{') + 1, stringFunc.lastIndexOf('}'))
try {
blob = new Blob([stringFunc], { 'type' : 'text/javascript' });
} catch (error) { // Backwards-compatibility
window.BlobBuilder = window.BlobBuilder || window.WebKitBlobBuilder || window.MozBlobBuilder;
blob = new BlobBuilder();
blob.append(stringFunc);
blob = blob.getBlob();
}
return (window.URL || window.webkitURL).createObjectURL(blob);
},
createWorker: function () {
return new Worker(this.functionToObjectURL(function () {
onmessage = function (event) {
var message = event.data;
postMessage({id: message.id, result: eval('(' + message.func + ')').apply(null, message.arguments)});
}
}));
},
generateTaskID: function () {
var id = Math.random(),
exists = false;
this.tasks.some(function (task) {
if (task.id === true) {
exists = true;
return true;
}
});
return exists ? this.generateTaskID() : id;
},
onWorkerMessage: function (event) {
var message = event.data,
taskIndex = null;
this.tasks.some(function (task, index) {
if (message.id === task.id) {
taskIndex = index;
return true;
}
});
if (taskIndex !== null) {
this.tasks[taskIndex].callback(message.result);
this.onTaskComplete(this);
this.tasks.splice(taskIndex, 1);
}
},
run: function ($options) {
var id = this.generateTaskID();
this.lastTaskTimestamp = new Date();
this.tasks.push({
id: id,
callback: $options.callback
})
this.worker.postMessage({
id: id,
arguments: $options.arguments,
func: String($options.function)
});
}
};
function TaskWorkerManager ($config) {
$config = $config || {};
this.maxWorkers = navigator.hardwareConcurrency || $config.maxWorkers || 4;
this.idleTimeout = $config.idleTimeout || 10000;
this.workers = [];
this.queue = [];
this.onWorkerTaskComplete = this.onWorkerTaskComplete.bind(this);
this.flushIdleWorkers = this.flushIdleWorkers.bind(this);
if (this.idleTimeout !== false) {
setInterval(this.flushIdleWorkers, 1000);
}
}
TaskWorkerManager.prototype = {
run: function (task) {
this.queue.push(task);
this.next();
},
next: function () {
if (!this.queue.length) return;
var worker = this.getWorker();
if (!worker) return;
var task = this.queue.shift();
worker.run(task);
},
onWorkerTaskComplete: function () {
this.next();
},
flushIdleWorkers: function () {
this.workers = this.workers.filter(function (worker) {
if (worker.tasks.length === 0 && new Date() - worker.lastTaskTimestamp > this.idleTimeout) {
worker.worker.terminate();
return false;
} else {
return true;
}
}, this);
},
getWorker: function () {
var idleWorkers = this.workers.filter(function (worker) {
return worker.tasks.length === 0;
});
if (idleWorkers.length) {
return idleWorkers[0];
} else if (this.workers.length < this.maxWorkers) {
return this.createWorker();
} else {
return null;
}
},
createWorker: function () {
var worker = new TaskWorker({
onTaskComplete: this.onWorkerTaskComplete
});
this.workers.push(worker);
return worker;
}
};
window.Task = new TaskWorkerManager();
})(window);
@icodeforlove
Copy link
Author

function quickSortAsync (items, callback) {
    Task.run({
        arguments: [items],
        function: function (items) {
            function swap(items, firstIndex, secondIndex){
                var temp = items[firstIndex];
                items[firstIndex] = items[secondIndex];
                items[secondIndex] = temp;
            }
            function partition(items, left, right) {
                var pivot   = items[Math.floor((right + left) / 2)],
                    i       = left,
                    j       = right;

                while (i <= j) {

                    while (items[i] < pivot) {
                        i++;
                    }

                    while (items[j] > pivot) {
                        j--;
                    }

                    if (i <= j) {
                        swap(items, i, j);
                        i++;
                        j--;
                    }
                }

                return i;
            }
            function quickSort(items, left, right) {
                var index;

                if (items.length > 1) {

                    left = typeof left != "number" ? 0 : left;
                    right = typeof right != "number" ? items.length - 1 : right;

                    index = partition(items, left, right);

                    if (left < index - 1) {
                        quickSort(items, left, index - 1);
                    }

                    if (index < right) {
                        quickSort(items, index, right);
                    }

                }

                return items;
            }

            return quickSort(items);
        },
        callback: callback
    });
}

quickSortAsync([1,5,3,4], function () {
    console.log(arguments) ;
});

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment