Spaces:
Running
Running
/** | |
* @author Deepkolos / https://github.com/deepkolos | |
*/ | |
export class WorkerPool { | |
constructor( pool = 4 ) { | |
this.pool = pool; | |
this.queue = []; | |
this.workers = []; | |
this.workersResolve = []; | |
this.workerStatus = 0; | |
} | |
_initWorker( workerId ) { | |
if ( ! this.workers[ workerId ] ) { | |
const worker = this.workerCreator(); | |
worker.addEventListener( 'message', this._onMessage.bind( this, workerId ) ); | |
this.workers[ workerId ] = worker; | |
} | |
} | |
_getIdleWorker() { | |
for ( let i = 0; i < this.pool; i ++ ) | |
if ( ! ( this.workerStatus & ( 1 << i ) ) ) return i; | |
return - 1; | |
} | |
_onMessage( workerId, msg ) { | |
const resolve = this.workersResolve[ workerId ]; | |
resolve && resolve( msg ); | |
if ( this.queue.length ) { | |
const { resolve, msg, transfer } = this.queue.shift(); | |
this.workersResolve[ workerId ] = resolve; | |
this.workers[ workerId ].postMessage( msg, transfer ); | |
} else { | |
this.workerStatus ^= 1 << workerId; | |
} | |
} | |
setWorkerCreator( workerCreator ) { | |
this.workerCreator = workerCreator; | |
} | |
setWorkerLimit( pool ) { | |
this.pool = pool; | |
} | |
postMessage( msg, transfer ) { | |
return new Promise( ( resolve ) => { | |
const workerId = this._getIdleWorker(); | |
if ( workerId !== - 1 ) { | |
this._initWorker( workerId ); | |
this.workerStatus |= 1 << workerId; | |
this.workersResolve[ workerId ] = resolve; | |
this.workers[ workerId ].postMessage( msg, transfer ); | |
} else { | |
this.queue.push( { resolve, msg, transfer } ); | |
} | |
} ); | |
} | |
dispose() { | |
this.workers.forEach( ( worker ) => worker.terminate() ); | |
this.workersResolve.length = 0; | |
this.workers.length = 0; | |
this.queue.length = 0; | |
this.workerStatus = 0; | |
} | |
} | |