-
Notifications
You must be signed in to change notification settings - Fork 6
Expand file tree
/
Copy path5-no-race.js
More file actions
94 lines (83 loc) · 1.98 KB
/
5-no-race.js
File metadata and controls
94 lines (83 loc) · 1.98 KB
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
85
86
87
88
89
90
91
92
93
94
'use strict';
const threads = require('node:worker_threads');
const { Worker, isMainThread } = threads;
const LOCKED = 0;
const UNLOCKED = 1;
class Mutex {
constructor(shared, offset = 0, initial = false) {
this.lock = new Int32Array(shared, offset, 1);
if (initial) Atomics.store(this.lock, 0, UNLOCKED);
this.owner = false;
}
enter() {
let prev = Atomics.exchange(this.lock, 0, LOCKED);
while (prev !== UNLOCKED) {
Atomics.wait(this.lock, 0, LOCKED);
prev = Atomics.exchange(this.lock, 0, LOCKED);
}
this.owner = true;
}
leave() {
if (!this.owner) return;
Atomics.store(this.lock, 0, UNLOCKED);
Atomics.notify(this.lock, 0, 1);
this.owner = false;
}
}
class Point {
constructor(data, x, y) {
this.data = data;
if (typeof x === 'number') data[0] = x;
if (typeof y === 'number') data[1] = y;
}
get x() {
return this.data[0];
}
set x(value) {
this.data[0] = value;
}
get y() {
return this.data[1];
}
set y(value) {
this.data[1] = value;
}
move(x, y) {
this.x += x;
this.y += y;
}
}
// Usage
if (isMainThread) {
const buffer = new SharedArrayBuffer(12);
const mutex = new Mutex(buffer, 0, true);
const array = new Int32Array(buffer, 4, 2);
const point = new Point(array, 0, 0);
console.dir({ mutex, point });
new Worker(__filename, { workerData: buffer });
new Worker(__filename, { workerData: buffer });
} else {
const { threadId, workerData } = threads;
const mutex = new Mutex(workerData);
const array = new Int32Array(workerData, 4, 2);
const point = new Point(array);
if (threadId === 1) {
for (let i = 0; i < 1000000; i++) {
mutex.enter();
point.move(1, 1);
mutex.leave();
}
mutex.enter();
console.dir({ point });
mutex.leave();
} else {
for (let i = 0; i < 1000000; i++) {
mutex.enter();
point.move(-1, -1);
mutex.leave();
}
mutex.enter();
console.dir({ point });
mutex.leave();
}
}