# Partager quelques threads de travail avec NEWTHREADPOOL()

> Démarrez un nombre fixe de workers, empruntez-en un avec pool.exec() quand il y a du travail, rendez-le avec release() et laissez les autres tâches attendre un worker libre.

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

`NEWTHREAD()` démarre un worker. Quand de nombreuses requêtes ont besoin du même travail lourd, un worker par requête est trop, et un seul worker les fait s'attendre sans aucun ordre. `NEWTHREADPOOL(name, count, [isfork])` démarre `count` workers de `workers/<name>.js` (un thread ; avec `isfork` à `true`, un processus enfant, comme `NEWFORK()`) et les distribue un à la fois.

- `pool.exec(function(worker, release) {})` attend qu'un worker soit libre et appelle votre fonction avec lui. Envoyez-lui le travail avec `worker.postMessage(value)`, lisez la réponse avec `worker.once('message', fn)` et **appelez `release()` quand vous avez terminé** : le worker retourne dans le pool et la prochaine tâche en attente le prend.
- Sans fonction, `pool.exec()` renvoie une promesse qui se résout avec `worker` (et le worker a `worker.release()`), si bien qu'il fonctionne avec `await`.
- Les tâches sont servies dans l'ordre où elles l'ont demandé. Le pool ne met pas en file les messages d'un worker : une seule tâche à la fois l'a.
- Le pool est aussi conservé dans `F.workers[name]`. `pool.workers` est la liste des workers.

Le fichier du worker est le même que pour `NEWTHREAD()` : `NEWTHREAD()` à l'intérieur renvoie le handle avec `worker.message` et `worker.postMessage()`. Ici chaque worker additionne les nombres et dit quel thread l'a fait.

```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 });
}
```
