# Deel een paar worker-threads met NEWTHREADPOOL()

> Start een vast aantal workers, leen er een met pool.exec() als er werk is, geef hem terug met release() en laat de andere taken wachten op een vrije worker.

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

`NEWTHREAD()` start één worker. Als veel verzoeken dezelfde zware taak nodig hebben, zijn het er te veel met een worker per verzoek, en één enkele worker laat ze zonder volgorde op elkaar wachten. `NEWTHREADPOOL(name, count, [isfork])` start `count` workers van `workers/<name>.js` (een thread; met `isfork` op `true` een kindproces, zoals `NEWFORK()`) en deelt ze één voor één uit.

- `pool.exec(function(worker, release) {})` wacht tot een worker vrij is en roept je functie ermee aan. Stuur hem het werk met `worker.postMessage(value)`, lees het antwoord met `worker.once('message', fn)` en **roep `release()` aan als je klaar bent**: de worker gaat terug naar de pool en de volgende wachtende taak neemt hem.
- Zonder functie geeft `pool.exec()` een promise terug die wordt opgelost met `worker` (en de worker heeft `worker.release()`), zodat het met `await` werkt.
- De taken worden bediend in de volgorde waarin ze erom vroegen. De pool zet de berichten van een worker niet in de wachtrij: één taak tegelijk heeft hem.
- De pool wordt ook bewaard in `F.workers[name]`. `pool.workers` is de lijst van de workers.

Het workerbestand is hetzelfde als voor `NEWTHREAD()`: `NEWTHREAD()` erin geeft de handle terug met `worker.message` en `worker.postMessage()`. Hier telt elke worker de getallen op en zegt welke thread het deed.

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