add hw2
This commit is contained in:
		
							
								
								
									
										149
									
								
								node_modules/langium/lib/parser/async-parser.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										149
									
								
								node_modules/langium/lib/parser/async-parser.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,149 @@ | ||||
| /****************************************************************************** | ||||
|  * Copyright 2023 TypeFox GmbH | ||||
|  * This program and the accompanying materials are made available under the | ||||
|  * terms of the MIT License, which is available in the project root. | ||||
|  ******************************************************************************/ | ||||
| import { Deferred, OperationCancelled } from '../utils/promise-utils.js'; | ||||
| import { Emitter } from '../utils/event.js'; | ||||
| /** | ||||
|  * Default implementation of the async parser which simply wraps the sync parser in a promise. | ||||
|  * | ||||
|  * @remarks | ||||
|  * A real implementation would create worker threads or web workers to offload the parsing work. | ||||
|  */ | ||||
| export class DefaultAsyncParser { | ||||
|     constructor(services) { | ||||
|         this.syncParser = services.parser.LangiumParser; | ||||
|     } | ||||
|     parse(text, _cancelToken) { | ||||
|         return Promise.resolve(this.syncParser.parse(text)); | ||||
|     } | ||||
| } | ||||
| export class AbstractThreadedAsyncParser { | ||||
|     constructor(services) { | ||||
|         /** | ||||
|          * The thread count determines how many threads are used to parse files in parallel. | ||||
|          * The default value is 8. Decreasing this value increases startup performance, but decreases parallel parsing performance. | ||||
|          */ | ||||
|         this.threadCount = 8; | ||||
|         /** | ||||
|          * The termination delay determines how long the parser waits for a thread to finish after a cancellation request. | ||||
|          * The default value is 200(ms). | ||||
|          */ | ||||
|         this.terminationDelay = 200; | ||||
|         this.workerPool = []; | ||||
|         this.queue = []; | ||||
|         this.hydrator = services.serializer.Hydrator; | ||||
|     } | ||||
|     initializeWorkers() { | ||||
|         while (this.workerPool.length < this.threadCount) { | ||||
|             const worker = this.createWorker(); | ||||
|             worker.onReady(() => { | ||||
|                 if (this.queue.length > 0) { | ||||
|                     const deferred = this.queue.shift(); | ||||
|                     if (deferred) { | ||||
|                         worker.lock(); | ||||
|                         deferred.resolve(worker); | ||||
|                     } | ||||
|                 } | ||||
|             }); | ||||
|             this.workerPool.push(worker); | ||||
|         } | ||||
|     } | ||||
|     async parse(text, cancelToken) { | ||||
|         const worker = await this.acquireParserWorker(cancelToken); | ||||
|         const deferred = new Deferred(); | ||||
|         let timeout; | ||||
|         // If the cancellation token is requested, we wait for a certain time before terminating the worker. | ||||
|         // Since the cancellation token lives longer than the parsing process, we need to dispose the event listener. | ||||
|         // Otherwise, we might accidentally terminate the worker after the parsing process has finished. | ||||
|         const cancellation = cancelToken.onCancellationRequested(() => { | ||||
|             timeout = setTimeout(() => { | ||||
|                 this.terminateWorker(worker); | ||||
|             }, this.terminationDelay); | ||||
|         }); | ||||
|         worker.parse(text).then(result => { | ||||
|             const hydrated = this.hydrator.hydrate(result); | ||||
|             deferred.resolve(hydrated); | ||||
|         }).catch(err => { | ||||
|             deferred.reject(err); | ||||
|         }).finally(() => { | ||||
|             cancellation.dispose(); | ||||
|             clearTimeout(timeout); | ||||
|         }); | ||||
|         return deferred.promise; | ||||
|     } | ||||
|     terminateWorker(worker) { | ||||
|         worker.terminate(); | ||||
|         const index = this.workerPool.indexOf(worker); | ||||
|         if (index >= 0) { | ||||
|             this.workerPool.splice(index, 1); | ||||
|         } | ||||
|     } | ||||
|     async acquireParserWorker(cancelToken) { | ||||
|         this.initializeWorkers(); | ||||
|         for (const worker of this.workerPool) { | ||||
|             if (worker.ready) { | ||||
|                 worker.lock(); | ||||
|                 return worker; | ||||
|             } | ||||
|         } | ||||
|         const deferred = new Deferred(); | ||||
|         cancelToken.onCancellationRequested(() => { | ||||
|             const index = this.queue.indexOf(deferred); | ||||
|             if (index >= 0) { | ||||
|                 this.queue.splice(index, 1); | ||||
|             } | ||||
|             deferred.reject(OperationCancelled); | ||||
|         }); | ||||
|         this.queue.push(deferred); | ||||
|         return deferred.promise; | ||||
|     } | ||||
| } | ||||
| export class ParserWorker { | ||||
|     get ready() { | ||||
|         return this._ready; | ||||
|     } | ||||
|     get onReady() { | ||||
|         return this.onReadyEmitter.event; | ||||
|     } | ||||
|     constructor(sendMessage, onMessage, onError, terminate) { | ||||
|         this.onReadyEmitter = new Emitter(); | ||||
|         this.deferred = new Deferred(); | ||||
|         this._ready = true; | ||||
|         this._parsing = false; | ||||
|         this.sendMessage = sendMessage; | ||||
|         this._terminate = terminate; | ||||
|         onMessage(result => { | ||||
|             const parseResult = result; | ||||
|             this.deferred.resolve(parseResult); | ||||
|             this.unlock(); | ||||
|         }); | ||||
|         onError(error => { | ||||
|             this.deferred.reject(error); | ||||
|             this.unlock(); | ||||
|         }); | ||||
|     } | ||||
|     terminate() { | ||||
|         this.deferred.reject(OperationCancelled); | ||||
|         this._terminate(); | ||||
|     } | ||||
|     lock() { | ||||
|         this._ready = false; | ||||
|     } | ||||
|     unlock() { | ||||
|         this._parsing = false; | ||||
|         this._ready = true; | ||||
|         this.onReadyEmitter.fire(); | ||||
|     } | ||||
|     parse(text) { | ||||
|         if (this._parsing) { | ||||
|             throw new Error('Parser worker is busy'); | ||||
|         } | ||||
|         this._parsing = true; | ||||
|         this.deferred = new Deferred(); | ||||
|         this.sendMessage(text); | ||||
|         return this.deferred.promise; | ||||
|     } | ||||
| } | ||||
| //# sourceMappingURL=async-parser.js.map | ||||
		Reference in New Issue
	
	Block a user
	 nik
					nik