# Condividi pochi thread di lavoro con NEWTHREADPOOL()

> Avvia un numero fisso di worker, prendine uno con pool.exec() quando c'è lavoro, restituiscilo con release() e lascia che gli altri lavori aspettino un worker libero.

Framework: total5
Product: Total.js 5 (total5@0.0.19)
Language: it
Content-SHA256: c726c3b50e640b4f2a36527fd34ffd422413323cee30a5106758c20d984ca6d1
Snapshot: c0700e321579725c5cf4f5ace1ad7d2866d1b4f93c24a63c0b41b6b7998e976c
Sources: total5-installed@total5@0.0.19
Review: not-recorded

`NEWTHREAD()` avvia un worker. Quando molte richieste hanno bisogno dello stesso lavoro pesante, un worker per richiesta sono troppi e un solo worker le fa aspettare l'una con l'altra senza alcun ordine. `NEWTHREADPOOL(name, count, [isfork])` avvia `count` worker di `workers/<name>.js` (un thread; con `isfork` impostato su `true` un processo figlio, come `NEWFORK()`) e li distribuisce uno alla volta.

- `pool.exec(function(worker, release) {})` aspetta che un worker sia libero e chiama la tua funzione con esso. Mandagli il lavoro con `worker.postMessage(value)`, leggi la risposta con `worker.once('message', fn)` e **chiama `release()` quando hai finito**: il worker torna nel pool e lo prende il lavoro successivo in attesa.
- Senza funzione, `pool.exec()` restituisce una promise che si risolve con `worker` (e il worker ha `worker.release()`), quindi funziona con `await`.
- I lavori sono serviti nell'ordine in cui hanno chiesto. Il pool non accoda i messaggi di un worker: un lavoro alla volta lo ha.
- Il pool è conservato anche in `F.workers[name]`. `pool.workers` è la lista dei worker.

Il file del worker è lo stesso di `NEWTHREAD()`: `NEWTHREAD()` al suo interno restituisce l'handle con `worker.message` e `worker.postMessage()`. Qui ogni worker somma i numeri e dice quale thread lo ha fatto.

```js workers/total.js
require('total5');

const worker = NEWTHREAD();

worker.message = function(message) {
	let total = 0;
	for (let i = 1; i <= message.to; i++)
		total += i;
	worker.postMessage({ to: message.to, total: total, thread: require('worker_threads').threadId });
};
```

```js controllers/total.js
exports.install = function() {
	ROUTE('GET /total/{to}/', total);
	ROUTE('GET /await/{to}/', total_await);
	ROUTE('GET /workers/', workers);
};

const pool = NEWTHREADPOOL('total', 2);

function total($) {
	pool.exec(function(worker, release) {
		worker.once('message', function(response) {
			release();
			$.json(response);
		});
		worker.postMessage({ to: +$.params.to });
	});
}

async function total_await($) {
	const worker = await pool.exec();
	worker.once('message', function(response) {
		worker.release();
		$.json(response);
	});
	worker.postMessage({ to: +$.params.to });
}

function workers($) {
	$.json({ workers: pool.workers.length, registered: F.workers.total === pool });
}
```
