Skip to content

Commit

Permalink
feat: locking timeout
Browse files Browse the repository at this point in the history
  • Loading branch information
anton-iskryzhytskyi committed Mar 15, 2020
1 parent 8aa05c7 commit 83bca61
Show file tree
Hide file tree
Showing 10 changed files with 45 additions and 110 deletions.
2 changes: 0 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,6 @@ await locks.request('Resource name', async lock => {
});
```

More examples [here](./examples/README.md)

## License

This implementation of Web Locks API is [MIT licensed](./LICENSE).
7 changes: 0 additions & 7 deletions examples/README.md

This file was deleted.

44 changes: 0 additions & 44 deletions examples/shared-resource/thread-main.js

This file was deleted.

38 changes: 0 additions & 38 deletions examples/shared-resource/thread-worker.js

This file was deleted.

1 change: 1 addition & 0 deletions test.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ const tests = [
'deadlock',
'recursive-deadlock',
'thread-main',
'lock-time',
];

(async () => {
Expand Down
18 changes: 18 additions & 0 deletions test/lock-time.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
'use strict';

const assert = require('assert').strict;
const { locks } = require('..');
const { sleep } = require('./test-utils');

const TIME_TO_PROCESS = 2000;
const TIME_TO_LOCK = 100;

module.exports = async () => {
const startTs = Date.now();

await locks.request('LockTime', { timeout: TIME_TO_LOCK }, async () => {
await sleep(TIME_TO_PROCESS);
});

assert.strictEqual(Date.now() - startTs < TIME_TO_PROCESS, true);
};
8 changes: 1 addition & 7 deletions test/steps.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,7 @@

const assert = require('assert').strict;
const { locks } = require('..');

const sleep = msec =>
new Promise(resolve => {
setTimeout(() => {
resolve();
}, msec);
});
const { sleep } = require('./test-utils');

let counter = 0;

Expand Down
10 changes: 10 additions & 0 deletions test/test-utils.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
'use strict';

const sleep = msec =>
new Promise(resolve => {
setTimeout(resolve, msec);
});

module.exports = {
sleep,
};
6 changes: 1 addition & 5 deletions test/thread-worker.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,10 @@
'use strict';

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

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

const sleep = msec =>
new Promise(resolve => {
setTimeout(resolve, msec);
});

(async () => {
if (threads.threadId === 2) {
await sleep(10);
Expand Down
21 changes: 14 additions & 7 deletions web-locks.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,13 @@ const UNLOCKED = 1;
let locks = null; // LockManager instance

class Lock {
constructor(name, mode = 'exclusive', buffer = null) {
constructor({ name, mode = 'exclusive', buffer = null, timeout = null }) {
this.name = name;
this.mode = mode; // 'exclusive' or 'shared'
this.queue = [];
this.owner = false;
this.trying = false;
this.timeout = timeout;
this.buffer = buffer ? buffer : new SharedArrayBuffer(4);
this.flag = new Int32Array(this.buffer, 0, 1);
if (!buffer) Atomics.store(this.flag, 0, UNLOCKED);
Expand All @@ -39,10 +40,16 @@ class Lock {
this.owner = true;
this.trying = false;
const { handler, resolve } = this.queue.shift();
handler(this).finally(() => {

const endWork = () => {
this.leave();
resolve();
});
};

if (typeof this.timeout === 'number') {
setTimeout(endWork, this.timeout);
}
handler(this).finally(endWork);
}

leave() {
Expand Down Expand Up @@ -89,11 +96,11 @@ class LockManager {
handler = options;
options = {};
}
const { mode = 'exclusive', signal = null } = options;
const { mode = 'exclusive', signal = null, timeout } = options;

let lock = this.collection.get(name);
if (!lock) {
lock = new Lock(name, mode);
lock = new Lock({ name, mode, timeout });
this.collection.set(name, lock);
const { buffer } = lock;
const message = { webLocks: true, kind: 'create', name, mode, buffer };
Expand Down Expand Up @@ -147,9 +154,9 @@ class LockManager {

receive(message) {
if (!message.webLocks) return;
const { kind, name, mode, buffer } = message;
const { kind, name, mode, buffer, timeout } = message;
if (kind === 'create') {
const lock = new Lock(name, mode, buffer);
const lock = new Lock({ name, mode, buffer, timeout });
this.collection.set(name, lock);
return;
}
Expand Down

0 comments on commit 83bca61

Please sign in to comment.