-
Notifications
You must be signed in to change notification settings - Fork 0
/
mandelbrot-renderer.js
84 lines (73 loc) · 2.17 KB
/
mandelbrot-renderer.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
import L from './leaflet-shim.js';
import Job from './job.js';
export default class MandelbrotRenderer {
constructor(numWorkers) {
this._jobs = new Map();
this._workers = [];
const boundOnMessage = this.onMessage.bind(this);
while (numWorkers--) {
const worker = new Worker('worker.js');
worker.onmessage = boundOnMessage;
worker.idle = true;
this._workers.push(worker);
}
}
getImageData(coords, tileSize, iterations, zoom) {
const job = Job({ coords, tileSize, iterations, zoom });
this._jobs.set(job.id, job);
// try to send message to idle worker, if any
for (const worker of this._workers) {
if (worker.idle) {
this.postJob(job, worker);
break;
}
}
return job.promise;
}
postJob(job, worker) {
if (!worker.idle) {
throw new Error('tried to post message to non-idle worker');
}
worker.idle = false;
job.posted = true;
worker.postMessage(job.message);
}
onMessage(event) {
const worker = event.target;
worker.idle = true;
// resolve deferred
const job = this._jobs.get(event.data.id);
if (job !== undefined) {
job.resolve(event.data.imageData);
this._jobs.delete(event.data.id);
}
// post new message if any deferreds still present
const nextJob = this.getNextJob();
if (nextJob !== undefined) {
this.postJob(nextJob, worker);
}
}
getNextJob() {
for (const [id, job] of this._jobs) {
if (!job.posted) {
return job;
}
}
}
clearJobs(predicate) {
if (predicate === undefined) {
this._jobs.clear();
return;
}
const toRemove = [];
for (const [id, job] of this._jobs) {
if (!job.posted && predicate(job)) {
toRemove.push(id);
}
}
toRemove.forEach(id => this._jobs.delete(id));
}
}
function highestIdFirst(a, b) {
return b.id - a.id;
}