]>
Commit | Line | Data |
---|---|---|
6dc67cda | 1 | 'use strict' |
2 | const { | |
3 | Worker, isMainThread, MessageChannel | |
4 | } = require('worker_threads') | |
5 | ||
6 | console.log('Fixed required') | |
7 | ||
8 | // FixedThreadPool , TrampolineThreadPool | |
9 | /** | |
10 | * A thread pool with a static number of threads , is possible to execute tasks in sync or async mode as you prefer | |
11 | * @author Alessandro Pio Ardizio | |
12 | * @since 0.0.1 | |
13 | */ | |
14 | class FixedThreadPool { | |
15 | /** | |
16 | * | |
17 | * @param {Number} numThreads Num of threads for this worker pool | |
18 | * @param {Object} an object with possible options for example maxConcurrency | |
19 | */ | |
c2dbbe2b | 20 | constructor (numThreads, task, opts) { |
6dc67cda | 21 | if (!isMainThread) { |
22 | throw new Error('Cannot start a thread pool from a worker thread !!!') | |
23 | } | |
24 | this.numThreads = numThreads | |
25 | this.workers = [] | |
c2dbbe2b | 26 | this.task = task |
6dc67cda | 27 | for (let i = 1; i <= numThreads; i++) { |
28 | const worker = new Worker(__filename) | |
29 | this.workers.push(worker) | |
c2dbbe2b | 30 | const { port1 } = new MessageChannel() |
31 | worker.emitter = port1 | |
6dc67cda | 32 | } |
33 | } | |
34 | ||
35 | /** | |
36 | * | |
37 | * @param {Function} task , a function to execute | |
38 | * @param {Any} the input for the task specified | |
39 | */ | |
40 | execute (task, data) { | |
41 | // TODO select a worker | |
42 | // configure worker to handle message with the specified task | |
c2dbbe2b | 43 | const idx = chooseWorker(0, this.numThreads - 1) |
44 | const worker = this.workers[idx] | |
45 | const id = generateID() | |
46 | const res = this._execute(worker, task, id) | |
47 | worker.emitter.emit(id, data) | |
6dc67cda | 48 | return res |
49 | } | |
50 | ||
c2dbbe2b | 51 | _execute (worker, task, id) { |
6dc67cda | 52 | return new Promise((resolve, reject) => { |
c2dbbe2b | 53 | console.log('Executing a task on worker thread ' + worker.threadId) |
54 | worker.emitter.once(id, (data) => { | |
55 | console.log('Receivd a message') | |
6dc67cda | 56 | try { |
57 | resolve(task(data)) | |
58 | } catch (e) { | |
59 | reject(e) | |
60 | } | |
61 | }) | |
62 | }) | |
63 | } | |
64 | } | |
65 | ||
c2dbbe2b | 66 | function chooseWorker (min, max) { |
67 | min = Math.ceil(min) | |
68 | max = Math.floor(max) | |
69 | return Math.floor(Math.random() * (max - min + 1)) + min | |
70 | } | |
71 | ||
72 | /** | |
73 | * Return an id to be associated to a node. | |
74 | */ | |
75 | const generateID = () => { | |
76 | return Math.random() | |
77 | .toString(36) | |
78 | .substring(7) | |
79 | } | |
80 | ||
6dc67cda | 81 | module.exports = FixedThreadPool |