parallel-es
Version:
Simple parallelization for EcmaScript
1,183 lines (1,063 loc) • 82.4 kB
JavaScript
(function webpackUniversalModuleDefinition(root, factory) {
if(typeof exports === 'object' && typeof module === 'object')
module.exports = factory(require("os"), require("child_process"));
else if(typeof define === 'function' && define.amd)
define(["os", "child_process"], factory);
else if(typeof exports === 'object')
exports["parallel-es"] = factory(require("os"), require("child_process"));
else
root["parallel-es"] = factory(root["os"], root["child_process"]);
})(this, function(__WEBPACK_EXTERNAL_MODULE_21__, __WEBPACK_EXTERNAL_MODULE_49__) {
return /******/ (function(modules) { // webpackBootstrap
/******/ // The module cache
/******/ var installedModules = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/
/******/ // Check if module is in cache
/******/ if(installedModules[moduleId]) {
/******/ return installedModules[moduleId].exports;
/******/ }
/******/ // Create a new module (and put it into the cache)
/******/ var module = installedModules[moduleId] = {
/******/ i: moduleId,
/******/ l: false,
/******/ exports: {}
/******/ };
/******/
/******/ // Execute the module function
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/
/******/ // Flag the module as loaded
/******/ module.l = true;
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/******/
/******/ // expose the modules object (__webpack_modules__)
/******/ __webpack_require__.m = modules;
/******/
/******/ // expose the module cache
/******/ __webpack_require__.c = installedModules;
/******/
/******/ // identity function for calling harmony imports with the correct context
/******/ __webpack_require__.i = function(value) { return value; };
/******/
/******/ // define getter function for harmony exports
/******/ __webpack_require__.d = function(exports, name, getter) {
/******/ if(!__webpack_require__.o(exports, name)) {
/******/ Object.defineProperty(exports, name, {
/******/ configurable: false,
/******/ enumerable: true,
/******/ get: getter
/******/ });
/******/ }
/******/ };
/******/
/******/ // getDefaultExport function for compatibility with non-harmony modules
/******/ __webpack_require__.n = function(module) {
/******/ var getter = module && module.__esModule ?
/******/ function getDefault() { return module['default']; } :
/******/ function getModuleExports() { return module; };
/******/ __webpack_require__.d(getter, 'a', getter);
/******/ return getter;
/******/ };
/******/
/******/ // Object.prototype.hasOwnProperty.call
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
/******/
/******/ // __webpack_public_path__
/******/ __webpack_require__.p = "";
/******/
/******/ // Load entry module and return exports
/******/ return __webpack_require__(__webpack_require__.s = 22);
/******/ })
/************************************************************************/
/******/ ([
/* 0 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
/**
* @module parallel
*/
/** */
/**
* Represents a function call
*/
class FunctionCall {
static create(func, ...args) {
return new FunctionCall(func, args);
}
/**
* Creates a function call for a function with with many arguments
* @param func the function to call
* @param params the parameters to pass
* @returns the function call
*/
static createUnchecked(func, ...params) {
return new FunctionCall(func, params);
}
/**
* Creates a function call instance from its serialized representation
* @param serialized the serialized function call
* @returns {FunctionCall} the function call
*/
static fromSerialized(serialized) {
return new FunctionCall(serialized.functionId, serialized.parameters);
}
constructor(func, params) {
this.func = func;
this.params = params;
}
}
/* harmony export (immutable) */ __webpack_exports__["a"] = FunctionCall;
/***/ }),
/* 1 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
/* harmony export (immutable) */ __webpack_exports__["a"] = functionId;
/* harmony export (immutable) */ __webpack_exports__["b"] = isFunctionId;
/**
* @module parallel
*/
/** */
/**
* Creates a function id
* @param namespace the namespace of the id
* @param id the unique id for this namespace
* @returns the function id
*/
function functionId(namespace, id) {
return {
_______isFunctionId: true,
identifier: `${namespace}-${id}`
};
}
/**
* Tests if the given object is a function id
* @param obj the object to test for
* @returns true if the object is a function id
*/
function isFunctionId(obj) {
return !!obj && obj._______isFunctionId === true;
}
/***/ }),
/* 2 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__function_function_id__ = __webpack_require__(1);
const ParallelWorkerFunctionIds = {
FILTER: __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__function_function_id__["a" /* functionId */])("parallel", 0),
IDENTITY: __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__function_function_id__["a" /* functionId */])("parallel", 1),
MAP: __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__function_function_id__["a" /* functionId */])("parallel", 2),
PARALLEL_JOB_EXECUTOR: __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__function_function_id__["a" /* functionId */])("parallel", 3),
RANGE: __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__function_function_id__["a" /* functionId */])("parallel", 4),
REDUCE: __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__function_function_id__["a" /* functionId */])("parallel", 5),
TIMES: __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__function_function_id__["a" /* functionId */])("parallel", 6),
TO_ITERATOR: __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__function_function_id__["a" /* functionId */])("parallel", 7)
};
/* harmony export (immutable) */ __webpack_exports__["a"] = ParallelWorkerFunctionIds;
/***/ }),
/* 3 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
/* harmony export (immutable) */ __webpack_exports__["a"] = toIterator;
/* harmony export (immutable) */ __webpack_exports__["b"] = toArray;
/* harmony export (immutable) */ __webpack_exports__["c"] = flattenArray;
/* harmony export (immutable) */ __webpack_exports__["d"] = concatInPlace;
/**
* Creates an iterator that iterates over the given array
* @param data the array
* @param T element type
* @returns the iterator
*/
/**
* Creates an iterator that iterates over the given array
* @param data the array
* @param T element type
* @returns the iterator
*/ function toIterator(data) {
return data[Symbol.iterator]();
}
/**
* Converts the given iterator to an array
* @param iterator the iterator that is to be converted into an array
* @param T element type
* @returns {T[]} the array representation of the given iterator
*/
function toArray(iterator) {
const result = [];
let current;
/* tslint:disable:no-conditional-assignment */
while (!(current = iterator.next()).done) {
result.push(current.value);
}
return result;
}
/**
* Flattens the given array.
* @param deepArray the array to flatten
* @param type of the array elements
* @returns returns an array containing all the values contained in the sub arrays of deep array.
*/
function flattenArray(deepArray) {
if (deepArray.length === 0) {
return [];
}
const [head, ...tail] = deepArray;
return Array.prototype.concat.apply(head, tail);
}
/**
* Appends the toAppend array to the target array. The result is stored in the target array (therefore, in place)
* @param target the first element to concat and as well as the target of the concatenation operation
* @param toAppend the array to append to target
*/
function concatInPlace(target, toAppend) {
const insertionIndex = target.length;
target.length += toAppend.length;
for (let i = 0; i < toAppend.length; ++i) {
target[insertionIndex + i] = toAppend[i];
}
return target;
}
/***/ }),
/* 4 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
/* harmony export (immutable) */ __webpack_exports__["a"] = isSerializedFunctionCall;
/**
* @module parallel
*/
/** */
/**
* Tests if the given object is a serialized function call
* @param potentialFunc a potentially serialized function call
* @returns {boolean} true if it is a serialized function call, false otherwise
*/
function isSerializedFunctionCall(potentialFunc) {
return !!potentialFunc && potentialFunc.______serializedFunctionCall === true;
}
/***/ }),
/* 5 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
/* harmony export (immutable) */ __webpack_exports__["h"] = initializeWorkerMessage;
/* harmony export (immutable) */ __webpack_exports__["i"] = scheduleTaskMessage;
/* harmony export (immutable) */ __webpack_exports__["d"] = requestFunctionMessage;
/* harmony export (immutable) */ __webpack_exports__["n"] = functionResponseMessage;
/* harmony export (immutable) */ __webpack_exports__["g"] = workerResultMessage;
/* harmony export (immutable) */ __webpack_exports__["f"] = functionExecutionError;
/* harmony export (immutable) */ __webpack_exports__["j"] = stopMessage;
/* harmony export (immutable) */ __webpack_exports__["c"] = isScheduleTask;
/* harmony export (immutable) */ __webpack_exports__["b"] = isInitializeMessage;
/* harmony export (immutable) */ __webpack_exports__["k"] = isFunctionRequest;
/* harmony export (immutable) */ __webpack_exports__["e"] = isFunctionResponse;
/* harmony export (immutable) */ __webpack_exports__["l"] = isWorkerResult;
/* harmony export (immutable) */ __webpack_exports__["m"] = isFunctionExecutionError;
/* harmony export (immutable) */ __webpack_exports__["a"] = isStopMesssage;
/**
* Creates an initialize worker message
* @param id the unique id of the worker
* @returns the initialize worker message
*/
function initializeWorkerMessage(id) {
return { type: 0 /* InitializeWorker */, workerId: id };
}
/**
* Creates a message to schedule the given task on a worker slave
* @param task the task to schedule
* @returns the schedule message
*/
function scheduleTaskMessage(task) {
return { task, type: 1 /* ScheduleTask */ };
}
/**
* Creates an {@link IFunctionRequest} message that requests the given function ids from the worker thread
* @param functionId the id of a function to request
* @param otherFunctionIds additional ids to request from the worker slave
* @returns the function request message
*/
function requestFunctionMessage(functionId, ...otherFunctionIds) {
return { functionIds: [functionId, ...otherFunctionIds], type: 2 /* FunctionRequest */ };
}
/**
* Creates a function response message containing the passed function definitions
* @param functions the function definitions to respond to the worker slave
* @returns the function response message
*/
function functionResponseMessage(functions, ...missingFunctionIds) {
return { functions, missingFunctions: missingFunctionIds, type: 3 /* FunctionResponse */ };
}
/**
* Creates a worker result message for the given result
* @param result the computed result for the scheduled task
* @returns the message
*/
function workerResultMessage(result) {
return { result, type: 4 /* WorkerResult */ };
}
/**
* Creates a function execution error message containing the given error
* @param error the error object thrown by the task computation
* @returns the message
*/
function functionExecutionError(error) {
const errorObject = {};
for (const prop of Object.getOwnPropertyNames(error)) {
errorObject[prop] = JSON.stringify(error[prop]);
}
return { error: errorObject, type: 5 /* FunctionExecutionError */ };
}
/**
* Creates a stop message
* @returns the message
*/
function stopMessage() {
return { type: 6 /* Stop */ };
}
/**
* Tests if the given message is an {@link IScheduleTaskMessage} message
* @param message the message to test
* @returns {boolean} {@code true} if the message is an {@link IScheduleTaskMessage}
*/
function isScheduleTask(message) {
return message.type === 1 /* ScheduleTask */;
}
/**
* Tests if the given message is an {@link IInitializeWorkerMessage} message
* @param message the message to test
* @returns {boolean} {@code true} if the message is an {@link IInitializeWorkerMessage}
*/
function isInitializeMessage(message) {
return message.type === 0 /* InitializeWorker */;
}
/**
* Tests if the given message is an {@link IFunctionRequest} message
* @param message the message to test
* @returns {boolean} {@code true} if the message is an {@link IFunctionRequest}
*/
function isFunctionRequest(message) {
return message.type === 2 /* FunctionRequest */;
}
/**
* Tests if the given message is an {@link IFunctionResponse} message
* @param message the message to test
* @returns {boolean} {@code true} if the message is an {@link IFunctionResponse}
*/
function isFunctionResponse(message) {
return message.type === 3 /* FunctionResponse */;
}
/**
* Tests if the given message is an {@link IWorkerResultMessage} message
* @param message the message to test
* @returns {boolean} {@code true} if the message is an {@link IWorkerResultMessage}
*/
function isWorkerResult(message) {
return message.type === 4 /* WorkerResult */;
}
/**
* Tests if the given message is an {@link IFunctionExecutionError} message
* @param message the message to test
* @returns {boolean} {@code true} if the message is an {@link IFunctionExecutionError}
*/
function isFunctionExecutionError(message) {
return message.type === 5 /* FunctionExecutionError */;
}
/**
* Tests if the given message is a stop message
* @param message the message to test
* @returns {boolean} {@code true} if the message is a stop message
*/
function isStopMesssage(message) {
return message.type === 6 /* Stop */;
}
/***/ }),
/* 6 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__scheduled_parallel_stream__ = __webpack_require__(39);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__resolved_parallel_stream__ = __webpack_require__(38);
/**
* Generic parallel stream that can be coordinated using the provided next, resolve and reject callbacks.
* @param TSubResult type of the sub results
* @param TEndResult type of the end result
*/
class ParallelStream {
/**
* Creates a new, generic parallel stream
* @param executor the executor function that gets passed the next, resolve and reject functions
*/
constructor(executor) {
/**
* Registered handlers that should be called for each sub result
* @type {Array}
* @private
*/
this.nextHandlers = [];
const next = (subResult, worker, valuesPerWorker) => this._next(subResult, worker, valuesPerWorker);
const reject = (reason) => this.reject(reason);
const resolve = (result) => this.resolve(result);
executor(next, resolve, reject);
this.promise = new Promise((res, rej) => {
this.resolve = res;
this.reject = rej;
});
}
/**
* Creates a new parallel that is based on the given input stream but transforms the end result using the given transformer
* @param inputStream the input stream on which the returned stream is based on
* @param transformer the transformer used to transform the end result
* @param TIn type of the input elements for this stream
* @param TIntermediate type of the end results from the input stream
* @param TResult end result after applying the transformer.
* @returns parallel stream that is based on the given input stream but with the transformed end result
*/
static transform(inputStream, transformer) {
let next;
let resolve;
let reject;
const transformedStream = new ParallelStream((nxt, rsolve, rject) => {
next = nxt;
resolve = rsolve;
reject = rject;
});
inputStream.subscribe(next, reject, (result) => resolve(transformer(result)));
return transformedStream;
}
/**
* Creates a new parallel stream for the given set of tasks.
* @param tasks the set of tasks that compute the results of the stream
* @param defaultResult the default result
* @param joiner the joiner to use to join two computed task results
* @param TTaskResult type of the task results
* @param TEndResult result of the created stream. Created by applying the end results of the stream to the joiner
* @returns stream for the given set of tasks
*/
static fromTasks(tasks, defaultResult, joiner) {
if (tasks.length === 0) {
return new __WEBPACK_IMPORTED_MODULE_1__resolved_parallel_stream__["a" /* ResolvedParallelStream */](defaultResult);
}
return new __WEBPACK_IMPORTED_MODULE_0__scheduled_parallel_stream__["a" /* ScheduledParallelStream */](tasks, defaultResult, joiner);
}
subscribe(onNext, onError, onComplete) {
this.nextHandlers.push(onNext);
if (onError || onComplete) {
this.promise.then(onComplete, onError);
}
return this;
}
then(onfulfilled, onrejected) {
return this.promise.then(onfulfilled, onrejected);
}
catch(onrejected) {
return this.promise.catch(onrejected);
}
_next(subResult, taskIndex, valuesPerTask) {
for (const nextHandler of this.nextHandlers) {
nextHandler.apply(undefined, arguments);
}
}
}
/* harmony export (immutable) */ __webpack_exports__["a"] = ParallelStream;
/***/ }),
/* 7 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
/**
* A very simple implementation of a map. Do not use with complex objects as Key.
* @param K type of the key
* @param V type of the value
*/
/**
* A very simple implementation of a map. Do not use with complex objects as Key.
* @param K type of the key
* @param V type of the value
*/ class SimpleMap {
constructor() {
this.data = {};
}
/**
* Gets the value for the given key if available
* @param key the key to look up
* @returns the looked up value or undefined if the map does not contain any value associated with the given key
*/
get(key) {
const internalKey = this.toInternalKey(key);
return this.has(key) ? this.data[internalKey] : undefined;
}
/**
* Tests if the map contains value stored by the given key
* @param key the key
* @returns true if the map contains a value by the given key, false otherwise
*/
has(key) {
return this.hasOwnProperty.call(this.data, this.toInternalKey(key));
}
/**
* Sets the value for the given key. If the map already contains a value stored by the given key, then this value is
* overridden
* @param key the key
* @param value the value to associate with the given key
*/
set(key, value) {
this.data[this.toInternalKey(key)] = value;
}
/**
* Clears all values from the map
*/
clear() {
this.data = {};
}
toInternalKey(key) {
return `@${key}`;
}
}
/* harmony export (immutable) */ __webpack_exports__["a"] = SimpleMap;
/***/ }),
/* 8 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
/**
* @module parallel
*/
/** */
/**
* Serializer for function calls
*/
class FunctionCallSerializer {
/**
* Creates a new instances that uses the given function registry to lookup the unique id of a function
* @param functionRegistry the registry for function lookup
*/
constructor(functionRegistry) {
this.functionRegistry = functionRegistry;
}
/**
* Serializes a call to the given function and using the passed parameters
* @param call the function call to serialize
* @returns a serialized representation of a call to the passed function using the given parameters
*/
serializeFunctionCall(call) {
const funcId = this.functionRegistry.getOrSetId(call.func);
return {
______serializedFunctionCall: true,
functionId: funcId,
parameters: call.params
};
}
}
/* harmony export (immutable) */ __webpack_exports__["a"] = FunctionCallSerializer;
/***/ }),
/* 9 */,
/* 10 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__dependent_parallel_chain_state__ = __webpack_require__(24);
/**
* State of a parallel chain whose job has been scheduled on the thread pool (or even where the computation already has completed).
* @param TElement type of the elements produced by the stream
*/
class ScheduledParallelChainState {
/**
* Creates a new state that is based on the given stream
* @param stream the stream for the scheduled tasks
* @param options the options used for the scheduled job
* @param environment the environment used for the scheduled job
*/
constructor(stream, options, environment) {
this.options = options;
this.environment = environment;
this.stream = stream;
}
resolve() {
return this;
}
chainOperation(operation) {
return new __WEBPACK_IMPORTED_MODULE_0__dependent_parallel_chain_state__["a" /* DependentParallelChainState */](this.stream, this.options, this.environment, [operation]);
}
addEnvironment(environment) {
return new __WEBPACK_IMPORTED_MODULE_0__dependent_parallel_chain_state__["a" /* DependentParallelChainState */](this.stream, this.options, this.environment.add(environment));
}
}
/* harmony export (immutable) */ __webpack_exports__["a"] = ScheduledParallelChainState;
/***/ }),
/* 11 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__slave_parallel_worker_functions__ = __webpack_require__(2);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__function_function_call__ = __webpack_require__(0);
/**
* Generator for arrays.
* Splits the array elements onto separate tasks.
* @param T type of the array elements
*/
class ParallelCollectionGenerator {
/**
* Creates a new instance over the given collection
* @param collection
*/
constructor(collection) {
this.collection = collection;
}
get length() {
return this.collection.length;
}
serializeSlice(index, numberOfItems, functionCallSerializer) {
const start = numberOfItems * index;
const end = start + numberOfItems;
return functionCallSerializer.serializeFunctionCall(__WEBPACK_IMPORTED_MODULE_1__function_function_call__["a" /* FunctionCall */].createUnchecked(__WEBPACK_IMPORTED_MODULE_0__slave_parallel_worker_functions__["a" /* ParallelWorkerFunctionIds */].TO_ITERATOR, this.collection.slice(start, end)));
}
}
/* harmony export (immutable) */ __webpack_exports__["a"] = ParallelCollectionGenerator;
/***/ }),
/* 12 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__common_function_function_id__ = __webpack_require__(1);
/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return __WEBPACK_IMPORTED_MODULE_0__common_function_function_id__["b"]; });
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__common_function_function_call__ = __webpack_require__(0);
/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "b", function() { return __WEBPACK_IMPORTED_MODULE_1__common_function_function_call__["a"]; });
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__common_function_serialized_function_call__ = __webpack_require__(4);
/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "c", function() { return __WEBPACK_IMPORTED_MODULE_2__common_function_serialized_function_call__["a"]; });
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__common_function_function_call_serializer__ = __webpack_require__(8);
/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "d", function() { return __WEBPACK_IMPORTED_MODULE_3__common_function_function_call_serializer__["a"]; });
/***/ }),
/* 13 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__util_simple_map__ = __webpack_require__(7);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__function_id__ = __webpack_require__(1);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__util_function_name__ = __webpack_require__(41);
/**
* Lookup table for resolving dynamic functions and their definitions
*/
class DynamicFunctionRegistry {
constructor() {
this.ids = new __WEBPACK_IMPORTED_MODULE_0__util_simple_map__["a" /* SimpleMap */]();
this.definitions = new __WEBPACK_IMPORTED_MODULE_0__util_simple_map__["a" /* SimpleMap */]();
this.lastId = 0;
}
/**
* Returns the unique id for the passed in function or assigns a new id to the given function and returns the newly assigned id
* @param func the function for which the unique id should be determined
* @returns the id of this function
*/
getOrSetId(func) {
if (__webpack_require__.i(__WEBPACK_IMPORTED_MODULE_1__function_id__["b" /* isFunctionId */])(func)) {
return func;
}
const source = func.toString();
let identifier = this.ids.get(source);
if (typeof (identifier) === "undefined") {
identifier = __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_1__function_id__["a" /* functionId */])("dynamic", ++this.lastId);
this.initDefinition(func, identifier);
}
return identifier;
}
/**
* Returns the definition of the function with the given id or undefined, if the id is not assigned to any function definition
* @param id the id of the function to resolve
* @returns the resolved function definition or undefined
* @throws if the function is a static function and therefore no definition exists.
*/
getDefinition(id) {
return this.definitions.get(id.identifier);
}
initDefinition(func, id) {
const source = func.toString();
const name = __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_2__util_function_name__["a" /* getFunctionName */])(func);
const args = source.substring(source.indexOf("(") + 1, source.indexOf(")")).split(",");
const body = source.substring(source.indexOf("{") + 1, source.lastIndexOf("}")).trim();
const definition = {
argumentNames: args.map(arg => arg.trim()),
body,
id,
name: name ? name : undefined
};
this.ids.set(source, id);
this.definitions.set(id.identifier, definition);
}
}
/* harmony export (immutable) */ __webpack_exports__["a"] = DynamicFunctionRegistry;
/***/ }),
/* 14 */,
/* 15 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
/* harmony export (immutable) */ __webpack_exports__["a"] = parallelFactory;
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__parallel_options__ = __webpack_require__(31);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__generator_parallel_collection_generator__ = __webpack_require__(11);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__generator_parallel_range_generator__ = __webpack_require__(28);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__generator_parallel_times_generator__ = __webpack_require__(29);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4__chain_parallel_chain_factory__ = __webpack_require__(25);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_5__function_function_id__ = __webpack_require__(1);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_6__function_function_call__ = __webpack_require__(0);
function parallelFactory(defaultOptions) {
function mergeOptions(userOptions) {
if (userOptions) {
if (userOptions.hasOwnProperty("threadPool") && typeof (userOptions.threadPool) === "undefined") {
throw new Error("The thread pool is mandatory and cannot be unset");
}
if (userOptions.hasOwnProperty("functionCallSerializer") && typeof (userOptions.functionCallSerializer) === "undefined") {
throw new Error("The function call serializer is mandatory and cannot be unset");
}
__webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__parallel_options__["a" /* validateOptions */])(userOptions);
}
return Object.assign({}, defaultOptions, userOptions);
}
return {
defaultOptions(options) {
if (options) {
defaultOptions = mergeOptions(options);
}
else {
return Object.assign({}, defaultOptions);
}
},
from(collection, options) {
return __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_4__chain_parallel_chain_factory__["a" /* createParallelChain */])(new __WEBPACK_IMPORTED_MODULE_1__generator_parallel_collection_generator__["a" /* ParallelCollectionGenerator */](collection), mergeOptions(options));
},
range(start, end, step, options) {
const generator = __WEBPACK_IMPORTED_MODULE_2__generator_parallel_range_generator__["a" /* ParallelRangeGenerator */].create(start, end, step);
return __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_4__chain_parallel_chain_factory__["a" /* createParallelChain */])(generator, mergeOptions(options));
},
times(n, generator, env, options) {
if (env) {
return __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_4__chain_parallel_chain_factory__["a" /* createParallelChain */])(__WEBPACK_IMPORTED_MODULE_3__generator_parallel_times_generator__["a" /* ParallelTimesGenerator */].create(n, generator), mergeOptions(options), env);
}
return __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_4__chain_parallel_chain_factory__["a" /* createParallelChain */])(__WEBPACK_IMPORTED_MODULE_3__generator_parallel_times_generator__["a" /* ParallelTimesGenerator */].create(n, generator), mergeOptions(options));
},
run(func, ...params) {
let functionCall;
if (__webpack_require__.i(__WEBPACK_IMPORTED_MODULE_5__function_function_id__["b" /* isFunctionId */])(func)) {
functionCall = __WEBPACK_IMPORTED_MODULE_6__function_function_call__["a" /* FunctionCall */].create(func, params);
}
else {
functionCall = __WEBPACK_IMPORTED_MODULE_6__function_function_call__["a" /* FunctionCall */].create(func, params);
}
const serializedCall = defaultOptions.functionCallSerializer.serializeFunctionCall(functionCall);
const task = {
main: serializedCall,
usedFunctionIds: [serializedCall.functionId]
};
return defaultOptions.threadPool.run(task);
}
};
}
/***/ }),
/* 16 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__abstract_parallel_scheduler__ = __webpack_require__(32);
/**
* Default implementation of a parallel scheduler.
* By default, creates 4 times as many tasks as the hardware concurrency allows ({@link IParallelOptions.maxConcurrencyLevel}).
*
* If the options define {@link IParallelOptions.maxValuesPerTask} or {@link IParallelOptions.minValuesPerTask}, then the
* values are adjusted accordingly.
*/
class DefaultParallelScheduler extends __WEBPACK_IMPORTED_MODULE_0__abstract_parallel_scheduler__["a" /* AbstractParallelScheduler */] {
getScheduling(totalNumberOfValues, options) {
let maxDegreeOfParallelism;
if (options.maxDegreeOfParallelism) {
maxDegreeOfParallelism = options.maxDegreeOfParallelism;
}
else {
maxDegreeOfParallelism = options.threadPool.maxThreads * 4;
}
let valuesPerTask = totalNumberOfValues / maxDegreeOfParallelism;
if (options.minValuesPerTask) {
valuesPerTask = Math.min(Math.max(valuesPerTask, options.minValuesPerTask), totalNumberOfValues);
}
if (options.maxValuesPerTask) {
valuesPerTask = Math.min(valuesPerTask, options.maxValuesPerTask);
}
valuesPerTask = Math.ceil(valuesPerTask);
return {
numberOfTasks: valuesPerTask === 0 ? 0 : Math.ceil(totalNumberOfValues / valuesPerTask),
valuesPerTask
};
}
}
/* harmony export (immutable) */ __webpack_exports__["a"] = DefaultParallelScheduler;
/***/ }),
/* 17 */,
/* 18 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__task_worker_task__ = __webpack_require__(40);
/**
* Default thread pool implementation that processes the scheduled functions in FIFO order.
*/
class DefaultThreadPool {
constructor(workerThreadFactory, options) {
this.workerThreadFactory = workerThreadFactory;
this.workers = [];
this.idleWorkers = [];
this.queue = [];
this.maxThreadsLimit = options.maxConcurrencyLevel;
}
get maxThreads() {
return this.maxThreadsLimit;
}
set maxThreads(limit) {
if (typeof (limit) !== "number" || limit % 1 !== 0 || limit <= 0) {
throw new Error(`The maxThreads limit (${limit}) has to be a positive integer larger than zero.`);
}
this.maxThreadsLimit = limit;
}
run(taskDefinition) {
const task = new __WEBPACK_IMPORTED_MODULE_0__task_worker_task__["a" /* WorkerTask */](taskDefinition);
this.queue.unshift(task);
this.schedulePendingTasks();
return task;
}
/**
* Schedules the tasks in the queue onto the available workers.
* A new worker is spawned when no more idle workers are available and the number of workers has not yet reached the concurrency limit.
* If no more idle workers are available and the concurrency limit has been reached then the tasks are left in queue.
*/
schedulePendingTasks() {
while (this.queue.length) {
let worker;
if (this.idleWorkers.length === 0 && this.workers.length < this.maxThreadsLimit) {
worker = this.workerThreadFactory.spawn();
this.workers.push(worker);
}
else if (this.idleWorkers.length > 0) {
worker = this.idleWorkers.pop();
}
if (!worker) {
return;
}
const task = this.queue.pop();
this.runTaskOnWorker(task, worker);
}
}
/**
* Starts the given task on the given worker. Resolves the task when the computation succeeds, rejects it otherwise.
* The task is resolved when the computation has succeeded or is rejected if the computation failed
* @param task the task to run on the given worker
* @param worker the worker to use to execute the task
*/
runTaskOnWorker(task, worker) {
if (task.isCancellationRequested) {
task.resolveCancelled();
this.releaseWorker(worker);
}
else {
worker.run(task.definition, (error, result) => {
if (error) {
task.reject(error);
}
else {
task.resolve(result);
}
this.releaseWorker(worker);
});
}
}
releaseWorker(worker) {
this.idleWorkers.push(worker);
this.schedulePendingTasks();
}
}
/* harmony export (immutable) */ __webpack_exports__["a"] = DefaultThreadPool;
/***/ }),
/* 19 */,
/* 20 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_child_process__ = __webpack_require__(49);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_child_process___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_child_process__);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__common_worker_default_worker_thread__ = __webpack_require__(44);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__child_process_worker_thread_slave_communication_channel__ = __webpack_require__(48);
class NodeWorkerThreadFactory {
constructor(functionLookupTable) {
this.functionLookupTable = functionLookupTable;
}
spawn() {
const child = __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0_child_process__["fork"])(this.getSlaveFileName());
const workerThread = new __WEBPACK_IMPORTED_MODULE_1__common_worker_default_worker_thread__["a" /* DefaultWorkerThread */](this.functionLookupTable, new __WEBPACK_IMPORTED_MODULE_2__child_process_worker_thread_slave_communication_channel__["a" /* ChildProcessWorkerThreadSlaveCommunicationChannel */](child));
workerThread.initialize();
return workerThread;
}
/**
* Hackedy Hack... Issue is, webpack handles calls to require resolve and replaces the call with the module id
* but that's not what we want. We actually want the require resolve call to be left until execution.
* NoParse is neither an option because then no requires / imports are resolved
* @returns {string} the file name of the slave
*/
getSlaveFileName() {
return eval("require").resolve("./node-slave.parallel");
}
}
/* harmony export (immutable) */ __webpack_exports__["a"] = NodeWorkerThreadFactory;
/***/ }),
/* 21 */
/***/ (function(module, exports) {
module.exports = require("os");
/***/ }),
/* 22 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
Object.defineProperty(__webpack_exports__, "__esModule", { value: true });
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_os__ = __webpack_require__(21);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_os___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_os__);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__common_function_dynamic_function_registry__ = __webpack_require__(13);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__common_function_function_call_serializer__ = __webpack_require__(8);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__node_worker_node_worker_thread_factory__ = __webpack_require__(20);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4__common_thread_pool_default_thread_pool__ = __webpack_require__(18);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_5__common_parallel_parallel_impl__ = __webpack_require__(15);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_6__common_parallel_scheduling_default_parallel_scheduler__ = __webpack_require__(16);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_7__shared__ = __webpack_require__(12);
/* harmony namespace reexport (by provided) */ __webpack_require__.d(__webpack_exports__, "isFunctionId", function() { return __WEBPACK_IMPORTED_MODULE_7__shared__["a"]; });
/* harmony namespace reexport (by provided) */ __webpack_require__.d(__webpack_exports__, "FunctionCall", function() { return __WEBPACK_IMPORTED_MODULE_7__shared__["b"]; });
/* harmony namespace reexport (by provided) */ __webpack_require__.d(__webpack_exports__, "isSerializedFunctionCall", function() { return __WEBPACK_IMPORTED_MODULE_7__shared__["c"]; });
/* harmony namespace reexport (by provided) */ __webpack_require__.d(__webpack_exports__, "FunctionCallSerializer", function() { return __WEBPACK_IMPORTED_MODULE_7__shared__["d"]; });
const functionLookupTable = new __WEBPACK_IMPORTED_MODULE_1__common_function_dynamic_function_registry__["a" /* DynamicFunctionRegistry */]();
const maxConcurrencyLevel = __WEBPACK_IMPORTED_MODULE_0_os__["cpus"]().length;
const functionCallSerializer = new __WEBPACK_IMPORTED_MODULE_2__common_function_function_call_serializer__["a" /* FunctionCallSerializer */](functionLookupTable);
const threadPool = new __WEBPACK_IMPORTED_MODULE_4__common_thread_pool_default_thread_pool__["a" /* DefaultThreadPool */](new __WEBPACK_IMPORTED_MODULE_3__node_worker_node_worker_thread_factory__["a" /* NodeWorkerThreadFactory */](functionLookupTable), { maxConcurrencyLevel });
/**
* The global parallel instance.
*/
const parallel = __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_5__common_parallel_parallel_impl__["a" /* parallelFactory */])({
functionCallSerializer,
scheduler: new __WEBPACK_IMPORTED_MODULE_6__common_parallel_scheduling_default_parallel_scheduler__["a" /* DefaultParallelScheduler */](),
threadPool
});
/* harmony default export */ __webpack_exports__["default"] = (parallel);
/***/ }),
/* 23 */,
/* 24 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__scheduled_parallel_chain_state__ = __webpack_require__(10);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__generator_parallel_collection_generator__ = __webpack_require__(11);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__util_arrays__ = __webpack_require__(3);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__stream_parallel_stream_impl__ = __webpack_require__(6);
/**
* The state of a parallel chain if additional operations should be performed on an already scheduled parallel chain.
*
* The state needs to wait for the previous parallel job to complete and then take that result to continue the additional
* computations.
*
* @param TPrevious Type of the array elements of the dependent stream
* @param TElement Type of the array elements of the resulting array
*/
class DependentParallelChainState {
/**
* Creates a new dependent stream
* @param previousStream the stream upon which the new stream depends on
* @param options the options used by this parallel job
* @param environment the environment used by the job
* @param operations the operations to performed when the previous stream has completed
*/
constructor(previousStream, options, environment, operations = []) {
this.previousStream = previousStream;
this.options = options;
this.environment = environment;
this.operations = operations;
}
resolve() {
let next;
let resolve;
let reject;
const stream = new __WEBPACK_IMPORTED_MODULE_3__stream_parallel_stream_impl__["a" /* ParallelStream */]((nxt, rsolve, rject) => {
next = nxt;
resolve = rsolve;
reject = rject;
});
this.previousStream.then(result => {
const tasks = this.options.scheduler.schedule({
environment: this.environment,
generator: new __WEBPACK_IMPORTED_MODULE_1__generator_parallel_collection_generator__["a" /* ParallelCollectionGenerator */](result),
operations: this.operations,
options: this.options
});
const wrappedStream = __WEBPACK_IMPORTED_MODULE_3__stream_parallel_stream_impl__["a" /* ParallelStream */].fromTasks(tasks, [], __WEBPACK_IMPORTED_MODULE_2__util_arrays__["d" /* concatInPlace */]);
wrappedStream.subscribe(next, reject, resolve);
}, reject);
return new __WEBPACK_IMPORTED_MODULE_0__scheduled_parallel_chain_state__["a" /* ScheduledParallelChainState */](stream, this.options, this.environment);
}
chainOperation(operation) {
return new DependentParallelChainState(this.previousStream, this.options, this.environment, [...this.operations, operation]);
}
addEnvironment(environment) {
return new DependentParallelChainState(this.previousStream, this.options, this.environment.add(environment), this.operations);
}
}
/* harmony export (immutable) */ __webpack_exports__["a"] = DependentParallelChainState;
/***/ }),
/* 25 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
/* harmony export (immutable) */ __webpack_exports__["a"] = createParallelChain;
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__pending_parallel_chain_state__ = __webpack_require__(27);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__parallel_chain_impl__ = __webpack_require__(26);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__parallel_environment_definition__ = __webpack_require__(30);
function createParallelChain(generator, options, sharedEnv, operations = []) {
let environment;
if (sharedEnv instanceof Array) {
environment = undefined;
operations = sharedEnv;
}
else {
environment = sharedEnv;
}
const chain = new __WEBPACK_IMPORTED_MODULE_1__parallel_chain_impl__["a" /* ParallelChainImpl */](new __WEBPACK_IMPORTED_MODULE_0__pending_parallel_chain_state__["a" /* PendingParallelChainState */](generator, options, __WEBPACK_IMPORTED_MODULE_2__parallel_environment_definition__["a" /* ParallelEnvironmentDefinition */].of(), operations));
return environment ? chain.inEnvironment(environment) : chain;
}
/***/ }),
/* 26 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__slave_parallel_worker_functions__ = __webpack_require__(2);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__function_function_call__ = __webpack_require__(0);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__stream_parallel_stream_impl__ = __webpack_require__(6);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__function_function_id__ = __webpack_require__(1);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4__function_serialized_function_call__ = __webpack_require__(4);
/**
* Implementation of a {@link IParallelChain}
*
* The implementation uses an internal state ({@link IParallelChainState}) to distinguishes between a not yet scheduled job ({@link PendingParallelChainState}),
* a job that has been scheduled but potentially not yet completed ({@link ScheduledParallelChainState}) and a job that
* is waiting for another one to complete, but has not yet been scheduled ({@link DependentParallelChainState}).
*
* @param TIn type of the elements created by the generator
* @param TEnv type of the job environment
* @param TOut type of the elements in the resulting array
*/
class ParallelChainImpl {
/**
* Creates a new parallel chain with the given state
* @param state the state of the chain
*/
constructor(state) {
this.state = state;
}
// region Chaining
inEnvironment(newEnv, ...params) {
let env;
if (typeof newEnv === "function" || __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_3__function_function_id__["b" /* isFunctionId */])(newEnv)) {
env = __WEBPACK_IMPORTED_MODULE_1__function_function_call__["a" /* FunctionCall */].createUnchecked(newEnv, ...params);
}
else if (__webpack_require__.i(__WEBPACK_IMPORTED_MODULE_4__function_serialized_function_call__["a" /* isSerializedFunctionCall */])(newEnv)) {
env = __WEBPACK_IMPORTED_MODULE_1__function_function_call__["a" /* FunctionCall */].fromSerialized(newEnv);
}
else {
env = newEnv;
}
return new ParallelChainImpl(this.state.addEnvironment(env));
}
map(mapper) {
return this._chain(__WEBPACK_IMPORTED_MODULE_1__function_function_call__["a" /* FunctionCall */].createUnchecked(__WEBPACK_IMPORTED_MODULE_0__slave_parallel_worker_functions__["a" /* ParallelWorkerFunctionIds */].MAP), __WEBPACK_IMPORTED_MODULE_1__function_function_call__["a" /* FunctionCall */].createUnchecked(mapper));
}
reduce(defaultValue, accumulator, combiner) {
const combineOperation = combiner || accumulator;
const reduced = this._chain(__WEBPACK_IMPORTED_MODULE_1__function_function_call__["a" /* FunctionCall */].createUnchecked(__WEBPACK_IMPORTED_MODULE_0__slave_parallel_worker_functions__["a" /* ParallelWorkerFunctionIds */].REDUCE, defaultValue), __WEBPACK_IMPORTED_MODULE_1__function_function_call__["a" /* FunctionCall */].createUnchecked(accumulator)).resolveChain();
r