const Worker = require("./WorkerClass");
module.exports = (input) => new Promise((resolve) => {
let N = 0; // count of threads
const tempList = [];
try {
while (true) {
tempList.push(new Worker("./worker"));
}
} catch (e) {
N = tempList.length;
tempList.forEach(w => {
w.delete();
})
}
const doSeveralWork = (arr) => {
return new Promise((res, rej) => {
try {
const worker = new Worker("./worker"); // создаём подпрограмму, которая займёт один из потоков
const resultList = [];
worker.onMessage = ({data}) => { // подписываемся на его сообщение
// тут работа выполнена, используем data и освобождаем процесс
resultList.push(data);
if (resultList.length === arr.length) {
worker.delete();
res(resultList);
}
};
arr.forEach(text => {
worker.postMessage(text); // отправляем сообщение подпрограмме, чтобы он начал работу
});
} catch (e) {
// свободных потоков нет, ждём освобождения и создаём инстанс подпрограммы повторно
rej(e);
}
})
};
if (input.length === 0) {
resolve("0");
return;
}
let process = async () => {
do {
const chunkSize = input.length / N;
const chunkList = [];
for (let i = 0; i < input.length; i += chunkSize) {
chunkList.push(input.slice(i, i + chunkSize));
}
const promiseList = chunkList.map(ch => doSeveralWork(ch));
const resList = await Promise.all(promiseList);
// [[1, 2], [2, 3]] -> [1, 2, 2, 3]
const resFlattened = Array.prototype.concat.apply([], resList);
input = [];
for (let i = 0; i < resFlattened.length; i += 2) {
if (i === resFlattened.length - 1) {
input.push(resFlattened[i] + resFlattened[i]);
} else {
input.push(resFlattened[i] + resFlattened[i + 1]);
}
}
} while (input.length !== 1);
return input;
}
process.then(resolve)
});