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 |