Created
March 3, 2020 14:56
-
-
Save DrOctavius/5446a58596eef3c0d4956c3b5c434ca8 to your computer and use it in GitHub Desktop.
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 () { | |
var URL = window.URL || window.webkitURL; | |
if (!URL) { | |
throw new Error('This browser does not support Blob URLs'); | |
} | |
if (!window.Worker) { | |
throw new Error('This browser does not support Web Workers'); | |
} | |
function RedyCRM_Multithread(threads) { | |
this.threads = Math.max(2, threads | 0); | |
this._queue = []; | |
this._queueSize = 0; | |
this._activeThreads = 0; | |
this._debug = { | |
start: 0, | |
end: 0, | |
time: 0 | |
}; | |
} | |
RedyCRM_Multithread.prototype._worker = { | |
JSON: function () { | |
var /**/name/**/ = (/**/func/**/); | |
self.addEventListener('message', function (e) { | |
var data = e.data; | |
var view = new DataView(data); | |
var len = data.byteLength; | |
var str = Array(len); | |
for (var i = 0; i < len; i++) { | |
str[i] = String.fromCharCode(view.getUint8(i)); | |
} | |
var args = JSON.parse(str.join('')); | |
var value = (/**/name/**/).apply(/**/name/**/, args); | |
try { | |
data = JSON.stringify(value); | |
} catch (e) { | |
throw new Error('Parallel function must return JSON serializable response'); | |
} | |
len = typeof (data) === 'undefined' ? 0 : data.length; | |
var buffer = new ArrayBuffer(len); | |
view = new DataView(buffer); | |
for (i = 0; i < len; i++) { | |
view.setUint8(i, data.charCodeAt(i) & 255); | |
} | |
self.postMessage(buffer, [buffer]); | |
self.close(); | |
}) | |
}, | |
Int32: function () { | |
var /**/name/**/ = (/**/func/**/); | |
self.addEventListener('message', function (e) { | |
var data = e.data; | |
var view = new DataView(data); | |
var len = data.byteLength / 4; | |
var arr = Array(len); | |
for (var i = 0; i < len; i++) { | |
arr[i] = view.getInt32(i * 4); | |
} | |
var value = (/**/name/**/).apply(/**/name/**/, arr); | |
if (!(value instanceof Array)) { | |
value = [value]; | |
} | |
len = value.length; | |
var buffer = new ArrayBuffer(len * 4); | |
view = new DataView(buffer); | |
for (i = 0; i < len; i++) { | |
view.setInt32(i * 4, value[i]); | |
} | |
self.postMessage(buffer, [buffer]); | |
self.close(); | |
}) | |
}, | |
Float64: function () { | |
var /**/name/**/ = (/**/func/**/); | |
self.addEventListener('message', function (e) { | |
var data = e.data; | |
var view = new DataView(data); | |
var len = data.byteLength / 8; | |
var arr = Array(len); | |
for (var i = 0; i < len; i++) { | |
arr[i] = view.getFloat64(i * 8); | |
} | |
var value = (/**/name/**/).apply(/**/name/**/, arr); | |
if (!(value instanceof Array)) { | |
value = [value]; | |
} | |
len = value.length; | |
var buffer = new ArrayBuffer(len * 8); | |
view = new DataView(buffer); | |
for (i = 0; i < len; i++) { | |
view.setFloat64(i * 8, value[i]); | |
} | |
self.postMessage(buffer, [buffer]); | |
self.close(); | |
}) | |
} | |
}; | |
RedyCRM_Multithread.prototype._encode = { | |
JSON: function (args) { | |
try { | |
var data = JSON.stringify(args); | |
} catch (e) { | |
throw new Error('Arguments provided to parallel function must be JSON serializable'); | |
} | |
len = data.length; | |
var buffer = new ArrayBuffer(len); | |
var view = new DataView(buffer); | |
for (var i = 0; i < len; i++) { | |
view.setUint8(i, data.charCodeAt(i) & 255); | |
} | |
return buffer; | |
}, | |
Int32: function (args) { | |
len = args.length; | |
var buffer = new ArrayBuffer(len * 4); | |
var view = new DataView(buffer); | |
for (var i = 0; i < len; i++) { | |
view.setInt32(i * 4, args[i]); | |
} | |
return buffer; | |
}, | |
Float64: function (args) { | |
len = args.length; | |
var buffer = new ArrayBuffer(len * 8); | |
var view = new DataView(buffer); | |
for (var i = 0; i < len; i++) { | |
view.setFloat64(i * 8, args[i]); | |
} | |
return buffer; | |
} | |
}; | |
RedyCRM_Multithread.prototype._decode = { | |
JSON: function (data) { | |
var view = new DataView(data); | |
var len = data.byteLength; | |
var str = Array(len); | |
for (var i = 0; i < len; i++) { | |
str[i] = String.fromCharCode(view.getUint8(i)); | |
} | |
if (!str.length) { | |
return; | |
} else { | |
return JSON.parse(str.join('')); | |
} | |
}, | |
Int32: function (data) { | |
var view = new DataView(data); | |
var len = data.byteLength / 4; | |
var arr = Array(len); | |
for (var i = 0; i < len; i++) { | |
arr[i] = view.getInt32(i * 4); | |
} | |
return arr; | |
}, | |
Float64: function (data) { | |
var view = new DataView(data); | |
var len = data.byteLength / 8; | |
var arr = Array(len); | |
for (var i = 0; i < len; i++) { | |
arr[i] = view.getFloat64(i * 8); | |
} | |
return arr; | |
}, | |
}; | |
RedyCRM_Multithread.prototype._execute = function (resource, args, type, callback) { | |
if (!this._activeThreads) { | |
this._debug.start = (new Date).valueOf(); | |
} | |
if (this._activeThreads < this.threads) { | |
this._activeThreads++; | |
var t = (new Date()).valueOf(); | |
var worker = new Worker(resource); | |
var buffer = this._encode[type](args); | |
var decode = this._decode[type]; | |
var self = this; | |
if (type === 'JSON') { | |
var listener = function (e) { | |
callback.call(self, decode(e.data)); | |
self.ready(); | |
}; | |
} else { | |
var listener = function (e) { | |
callback.apply(self, decode(e.data)); | |
self.ready(); | |
}; | |
} | |
worker.addEventListener('message', listener); | |
worker.postMessage(buffer, [buffer]); | |
} else { | |
this._queueSize++; | |
this._queue.push([resource, args, type, callback]); | |
} | |
}; | |
RedyCRM_Multithread.prototype.ready = function () { | |
this._activeThreads--; | |
if (this._queueSize) { | |
this._execute.apply(this, this._queue.shift()); | |
this._queueSize--; | |
} else if (!this._activeThreads) { | |
this._debug.end = (new Date).valueOf(); | |
this._debug.time = this._debug.end - this._debug.start; | |
} | |
}; | |
RedyCRM_Multithread.prototype._prepare = function (fn, type) { | |
fn = fn; | |
var name = fn.name; | |
var fnStr = fn.toString(); | |
if (!name) { | |
name = '$' + ((Math.random() * 10) | 0); | |
while (fnStr.indexOf(name) !== -1) { | |
name += ((Math.random() * 10) | 0); | |
} | |
} | |
var script = this._worker[type] | |
.toString() | |
.replace(/^.*?[\n\r]+/gi, '') | |
.replace(/\}[\s]*$/, '') | |
.replace(/\/\*\*\/name\/\*\*\//gi, name) | |
.replace(/\/\*\*\/func\/\*\*\//gi, fnStr); | |
var resource = URL.createObjectURL(new Blob([script], {type: 'text/javascript'})); | |
return resource; | |
}; | |
RedyCRM_Multithread.prototype.process = function (fn, callback) { | |
var resource = this._prepare(fn, 'JSON'); | |
var self = this; | |
return function () { | |
self._execute(resource, [].slice.call(arguments), 'JSON', callback) | |
}; | |
}; | |
RedyCRM_Multithread.prototype.processInt32 = function (fn, callback) { | |
var resource = this._prepare(fn, 'Int32'); | |
var self = this; | |
return function () { | |
self._execute(resource, [].slice.call(arguments), 'Int32', callback) | |
}; | |
}; | |
RedyCRM_Multithread.prototype.processFloat64 = function (fn, callback) { | |
var resource = this._prepare(fn, 'Float64'); | |
var self = this; | |
return function () { | |
self._execute(resource, [].slice.call(arguments), 'Float64', callback) | |
}; | |
}; | |
window['RedyCRM_Multithread'] = RedyCRM_Multithread; | |
}(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment