Skip to content

Commit 83bca61

Browse files
feat: locking timeout
1 parent 8aa05c7 commit 83bca61

10 files changed

Lines changed: 45 additions & 110 deletions

File tree

README.md

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,6 @@ await locks.request('Resource name', async lock => {
3939
});
4040
```
4141

42-
More examples [here](./examples/README.md)
43-
4442
## License
4543

4644
This implementation of Web Locks API is [MIT licensed](./LICENSE).

examples/README.md

Lines changed: 0 additions & 7 deletions
This file was deleted.

examples/shared-resource/thread-main.js

Lines changed: 0 additions & 44 deletions
This file was deleted.

examples/shared-resource/thread-worker.js

Lines changed: 0 additions & 38 deletions
This file was deleted.

test.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ const tests = [
88
'deadlock',
99
'recursive-deadlock',
1010
'thread-main',
11+
'lock-time',
1112
];
1213

1314
(async () => {

test/lock-time.js

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
'use strict';
2+
3+
const assert = require('assert').strict;
4+
const { locks } = require('..');
5+
const { sleep } = require('./test-utils');
6+
7+
const TIME_TO_PROCESS = 2000;
8+
const TIME_TO_LOCK = 100;
9+
10+
module.exports = async () => {
11+
const startTs = Date.now();
12+
13+
await locks.request('LockTime', { timeout: TIME_TO_LOCK }, async () => {
14+
await sleep(TIME_TO_PROCESS);
15+
});
16+
17+
assert.strictEqual(Date.now() - startTs < TIME_TO_PROCESS, true);
18+
};

test/steps.js

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,7 @@
22

33
const assert = require('assert').strict;
44
const { locks } = require('..');
5-
6-
const sleep = msec =>
7-
new Promise(resolve => {
8-
setTimeout(() => {
9-
resolve();
10-
}, msec);
11-
});
5+
const { sleep } = require('./test-utils');
126

137
let counter = 0;
148

test/test-utils.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
'use strict';
2+
3+
const sleep = msec =>
4+
new Promise(resolve => {
5+
setTimeout(resolve, msec);
6+
});
7+
8+
module.exports = {
9+
sleep,
10+
};

test/thread-worker.js

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,10 @@
11
'use strict';
22

33
const threads = require('worker_threads');
4+
const { sleep } = require('./test-utils');
45

56
const { locks } = require('..');
67

7-
const sleep = msec =>
8-
new Promise(resolve => {
9-
setTimeout(resolve, msec);
10-
});
11-
128
(async () => {
139
if (threads.threadId === 2) {
1410
await sleep(10);

web-locks.js

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,13 @@ const UNLOCKED = 1;
1111
let locks = null; // LockManager instance
1212

1313
class Lock {
14-
constructor(name, mode = 'exclusive', buffer = null) {
14+
constructor({ name, mode = 'exclusive', buffer = null, timeout = null }) {
1515
this.name = name;
1616
this.mode = mode; // 'exclusive' or 'shared'
1717
this.queue = [];
1818
this.owner = false;
1919
this.trying = false;
20+
this.timeout = timeout;
2021
this.buffer = buffer ? buffer : new SharedArrayBuffer(4);
2122
this.flag = new Int32Array(this.buffer, 0, 1);
2223
if (!buffer) Atomics.store(this.flag, 0, UNLOCKED);
@@ -39,10 +40,16 @@ class Lock {
3940
this.owner = true;
4041
this.trying = false;
4142
const { handler, resolve } = this.queue.shift();
42-
handler(this).finally(() => {
43+
44+
const endWork = () => {
4345
this.leave();
4446
resolve();
45-
});
47+
};
48+
49+
if (typeof this.timeout === 'number') {
50+
setTimeout(endWork, this.timeout);
51+
}
52+
handler(this).finally(endWork);
4653
}
4754

4855
leave() {
@@ -89,11 +96,11 @@ class LockManager {
8996
handler = options;
9097
options = {};
9198
}
92-
const { mode = 'exclusive', signal = null } = options;
99+
const { mode = 'exclusive', signal = null, timeout } = options;
93100

94101
let lock = this.collection.get(name);
95102
if (!lock) {
96-
lock = new Lock(name, mode);
103+
lock = new Lock({ name, mode, timeout });
97104
this.collection.set(name, lock);
98105
const { buffer } = lock;
99106
const message = { webLocks: true, kind: 'create', name, mode, buffer };
@@ -147,9 +154,9 @@ class LockManager {
147154

148155
receive(message) {
149156
if (!message.webLocks) return;
150-
const { kind, name, mode, buffer } = message;
157+
const { kind, name, mode, buffer, timeout } = message;
151158
if (kind === 'create') {
152-
const lock = new Lock(name, mode, buffer);
159+
const lock = new Lock({ name, mode, buffer, timeout });
153160
this.collection.set(name, lock);
154161
return;
155162
}

0 commit comments

Comments
 (0)