103 lines
		
	
	
		
			1.7 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
		
		
			
		
	
	
			103 lines
		
	
	
		
			1.7 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
|  | /** | ||
|  |  * @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; | ||
|  | 
 | ||
|  | 	} | ||
|  | 
 | ||
|  | } |