xtorcga
Version:
Xtor Compute Geometry Algorithm Libary 计算几何算法库
223 lines (182 loc) • 7.16 kB
text/typescript
import { isDefined, Undefinable } from "src/utils/types";
function canTransferArrayBuffer() {
if (!isDefined(TaskProcessor._canTransferArrayBuffer)) {
var worker = new Worker(getWorkerUrl("Workers/transferTypedArrayTest.js"));
worker.postMessage = (worker as any).webkitPostMessage || worker.postMessage
var value = 99;
var array = new Int8Array([value]);
try {
// postMessage might fail with a DataCloneError
// if transferring array buffers is not supported.
worker.postMessage(
{
array: array,
},
[array.buffer]
);
} catch (e) {
TaskProcessor._canTransferArrayBuffer = false;
return TaskProcessor._canTransferArrayBuffer;
}
var deferred = new Promise(() => { });
worker.onmessage = (event) => {
var array = event.data.array;
// some versions of Firefox silently fail to transfer typed arrays.
// https://bugzilla.mozilla.org/show_bug.cgi?id=841904
// Check to make sure the value round-trips successfully.
var result = isDefined(array) && array[0] === value;
new Promise((resolve, reject) => {
resolve(result);
}).then(() => {
TaskProcessor._canTransferArrayBuffer = true;
});
worker.terminate();
TaskProcessor._canTransferArrayBuffer = result;
};
}
return TaskProcessor._canTransferArrayBuffer;
}
function completeTask(processor: any, data: any) {
--processor._activeTasks;
var id = data.id;
if (!isDefined(id)) {
// This is not one of ours.
return;
}
var deferreds = processor._deferreds;
var deferred = deferreds[id];
if (isDefined(data.error)) {
var error = data.error;
if (error.name === "RuntimeError") {
error = console.log(data.error.message);
} else if (error.name === "DeveloperError") {
error = console.log(data.error.message);
}
// taskCompletedEvent.raiseEvent(error);
deferred.reject(error);
} else {
// taskCompletedEvent.raiseEvent();
deferred.resolve(data.result);
}
delete deferreds[id];
}
function getWorkerUrl(moduleID: any) {
var url = moduleID;
// if (isCrossOriginUrl(url)) {
// //to load cross-origin, create a shim worker from a blob URL
// var script = 'importScripts("' + url + '");';
// var blob;
// try {
// blob = new Blob([script], {
// type: "application/javascript",
// });
// } catch (e) {
// var BlobBuilder =
// (window as any).BlobBuilder ||
// (window as any).WebKitBlobBuilder ||
// (window as any).MozBlobBuilder ||
// (window as any).MSBlobBuilder;
// var blobBuilder = new BlobBuilder();
// blobBuilder.append(script);
// blob = blobBuilder.getBlob("application/javascript");
// }
// var URL = window.URL || window.webkitURL;
// url = URL.createObjectURL(blob);
// }
return url;
}
var bootstrapperUrlResult: any;
function getBootstrapperUrl() {
if (!isDefined(bootstrapperUrlResult)) {
bootstrapperUrlResult = getWorkerUrl("Workers/cesiumWorkerBootstrapper.js");
}
return bootstrapperUrlResult;
}
function createWorker(processor: TaskProcessor) {
var worker = new Worker(getBootstrapperUrl());
worker.postMessage = (<any>worker).webkitPostMessage || worker.postMessage;
var bootstrapMessage = {
};
worker.postMessage(bootstrapMessage);
worker.onmessage = function (event) {
completeTask(processor, event.data);
};
return worker;
}
var emptyTransferableObjectArray: any = [];
/**
* A wrapper around a web worker that allows scheduling tasks for a given worker,
* returning results asynchronously via a promise.
*
* The Worker is not constructed until a task is scheduled.
*
* @alias TaskProcessor
* @constructor
*
* @param {String} workerPath The Url to the worker. This can either be an absolute path or relative to the Cesium Workers folder.
* @param {Number} [maximumActiveTasks=5] The maximum number of active tasks. Once exceeded,
* scheduleTask will not queue any more tasks, allowing
* work to be rescheduled in future frames.
*/
export class TaskProcessor {
static _defaultWorkerModulePrefix = "Workers/";
static _workerModulePrefix = TaskProcessor._defaultWorkerModulePrefix;
static _canTransferArrayBuffer: boolean = true;
private _workerPath: string = '';
private _maximumActiveTasks: number;
private _activeTasks: number;
_deferreds: any = {};
private _nextID: number;
private _worker: Undefinable<Worker>
constructor(workerPath: string, maximumActiveTasks: number = 5) {
this._workerPath = TaskProcessor._workerModulePrefix + workerPath;
this._maximumActiveTasks = maximumActiveTasks;
this._activeTasks = 0;
this._deferreds = {};
this._nextID = 0;
}
scheduleTask(parameters: any, transferableObjects: any) {
if (!isDefined(this._worker)) {
this._worker = createWorker(this);
}
if (this._activeTasks >= this._maximumActiveTasks) {
return undefined;
}
++this._activeTasks;
var processor = this;
var deferred = new Promise((resolve, reject) => {
resolve(canTransferArrayBuffer())
}).then(function (canTransferArrayBuffer) {
if (!isDefined(transferableObjects)) {
transferableObjects = emptyTransferableObjectArray;
} else if (!canTransferArrayBuffer) {
transferableObjects.length = 0;
}
var id = processor._nextID++;
processor._deferreds[id] = deferred;
if (processor._worker)
processor._worker.postMessage(
{
id: id,
parameters: parameters,
canTransferArrayBuffer: canTransferArrayBuffer,
},
transferableObjects
);
});
}
isDestroyed() {
return false;
};
/**
* Destroys this object. This will immediately terminate the Worker.
* <br /><br />
* Once an object is destroyed, it should not be used; calling any function other than
* <code>isDestroyed</code> will result in a {@link DeveloperError} exception.
*/
destroy() {
if (isDefined(this._worker)) {
this._worker!.terminate();
}
};
}