@matrixai/async-locks
Advanced tools
Comparing version 2.1.1 to 2.2.0
@@ -8,2 +8,5 @@ import { AbstractError } from '@matrixai/errors'; | ||
} | ||
export { ErrorAsyncLocks, ErrorAsyncLocksTimeout }; | ||
declare class ErrorAsyncLocksLockBoxConflict<T> extends ErrorAsyncLocks<T> { | ||
static description: string; | ||
} | ||
export { ErrorAsyncLocks, ErrorAsyncLocksTimeout, ErrorAsyncLocksLockBoxConflict, }; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.ErrorAsyncLocksTimeout = exports.ErrorAsyncLocks = void 0; | ||
exports.ErrorAsyncLocksLockBoxConflict = exports.ErrorAsyncLocksTimeout = exports.ErrorAsyncLocks = void 0; | ||
const errors_1 = require("@matrixai/errors"); | ||
@@ -12,3 +12,7 @@ class ErrorAsyncLocks extends errors_1.AbstractError { | ||
exports.ErrorAsyncLocksTimeout = ErrorAsyncLocksTimeout; | ||
ErrorAsyncLocksTimeout.description = 'Async lock timeout'; | ||
ErrorAsyncLocksTimeout.description = 'Async locks timeout'; | ||
class ErrorAsyncLocksLockBoxConflict extends ErrorAsyncLocks { | ||
} | ||
exports.ErrorAsyncLocksLockBoxConflict = ErrorAsyncLocksLockBoxConflict; | ||
ErrorAsyncLocksLockBoxConflict.description = 'LockBox cannot lock same ID with different Lockable classes'; | ||
//# sourceMappingURL=errors.js.map |
export { default as Lock } from './Lock'; | ||
export { default as RWLockReader } from './RWLockReader'; | ||
export { default as RWLockWriter } from './RWLockWriter'; | ||
export { default as LockBox } from './LockBox'; | ||
export * as utils from './utils'; | ||
export * as errors from './errors'; | ||
export * from './types'; |
@@ -28,3 +28,3 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.errors = exports.utils = exports.RWLockWriter = exports.RWLockReader = exports.Lock = void 0; | ||
exports.errors = exports.utils = exports.LockBox = exports.RWLockWriter = exports.RWLockReader = exports.Lock = void 0; | ||
var Lock_1 = require("./Lock"); | ||
@@ -36,2 +36,4 @@ Object.defineProperty(exports, "Lock", { enumerable: true, get: function () { return __importDefault(Lock_1).default; } }); | ||
Object.defineProperty(exports, "RWLockWriter", { enumerable: true, get: function () { return __importDefault(RWLockWriter_1).default; } }); | ||
var LockBox_1 = require("./LockBox"); | ||
Object.defineProperty(exports, "LockBox", { enumerable: true, get: function () { return __importDefault(LockBox_1).default; } }); | ||
exports.utils = __importStar(require("./utils")); | ||
@@ -38,0 +40,0 @@ exports.errors = __importStar(require("./errors")); |
import type { ResourceAcquire } from '@matrixai/resources'; | ||
import type { Lockable } from './types'; | ||
import { Mutex } from 'async-mutex'; | ||
declare class Lock { | ||
declare class Lock implements Lockable { | ||
protected _lock: Mutex; | ||
@@ -10,5 +11,8 @@ protected _count: number; | ||
waitForUnlock(timeout?: number): Promise<void>; | ||
withF<T>(f: (lock: Lock) => Promise<T>, timeout?: number): Promise<T>; | ||
withG<T, TReturn, TNext>(g: (lock: Lock) => AsyncGenerator<T, TReturn, TNext>, timeout?: number): AsyncGenerator<T, TReturn, TNext>; | ||
withF<T>(...params: [...([timeout: number] | []), (lock: Lock) => Promise<T>]): Promise<T>; | ||
withG<T, TReturn, TNext>(...params: [ | ||
...([timeout: number] | []), | ||
(lock: Lock) => AsyncGenerator<T, TReturn, TNext> | ||
]): AsyncGenerator<T, TReturn, TNext>; | ||
} | ||
export default Lock; |
@@ -61,6 +61,10 @@ "use strict"; | ||
} | ||
async withF(f, timeout) { | ||
async withF(...params) { | ||
const f = params.pop(); | ||
const timeout = params[0]; | ||
return (0, resources_1.withF)([this.lock(timeout)], ([lock]) => f(lock)); | ||
} | ||
withG(g, timeout) { | ||
withG(...params) { | ||
const g = params.pop(); | ||
const timeout = params[0]; | ||
return (0, resources_1.withG)([this.lock(timeout)], ([lock]) => g(lock)); | ||
@@ -67,0 +71,0 @@ } |
import type { MutexInterface } from 'async-mutex'; | ||
import type { ResourceAcquire } from '@matrixai/resources'; | ||
import type { Lockable } from './types'; | ||
import { Mutex } from 'async-mutex'; | ||
@@ -7,9 +8,11 @@ /** | ||
*/ | ||
declare class RWLockReader { | ||
declare class RWLockReader implements Lockable { | ||
protected _readerCount: number; | ||
protected _writerCount: number; | ||
protected lock: Mutex; | ||
protected _lock: Mutex; | ||
protected release: MutexInterface.Releaser; | ||
lock(type: 'read' | 'write', timeout?: number): ResourceAcquire<RWLockReader>; | ||
read(timeout?: number): ResourceAcquire<RWLockReader>; | ||
write(timeout?: number): ResourceAcquire<RWLockReader>; | ||
get count(): number; | ||
get readerCount(): number; | ||
@@ -19,7 +22,21 @@ get writerCount(): number; | ||
waitForUnlock(timeout?: number): Promise<void>; | ||
withReadF<T>(f: (lock: RWLockReader) => Promise<T>, timeout?: number): Promise<T>; | ||
withWriteF<T>(f: (lock: RWLockReader) => Promise<T>, timeout?: number): Promise<T>; | ||
withReadG<T, TReturn, TNext>(g: (lock: RWLockReader) => AsyncGenerator<T, TReturn, TNext>, timeout?: number): AsyncGenerator<T, TReturn, TNext>; | ||
withWriteG<T, TReturn, TNext>(g: (lock: RWLockReader) => AsyncGenerator<T, TReturn, TNext>, timeout?: number): AsyncGenerator<T, TReturn, TNext>; | ||
withF<T>(...params: [ | ||
...([type: 'read' | 'write', timeout: number] | [type: 'read' | 'write'] | []), | ||
(lock: RWLockReader) => Promise<T> | ||
]): Promise<T>; | ||
withReadF<T>(...params: [...([timeout: number] | []), (lock: RWLockReader) => Promise<T>]): Promise<T>; | ||
withWriteF<T>(...params: [...([timeout: number] | []), (lock: RWLockReader) => Promise<T>]): Promise<T>; | ||
withG<T, TReturn, TNext>(...params: [ | ||
...([type: 'read' | 'write', timeout: number] | [type: 'read' | 'write'] | []), | ||
(lock: RWLockReader) => AsyncGenerator<T, TReturn, TNext> | ||
]): AsyncGenerator<T, TReturn, TNext>; | ||
withReadG<T, TReturn, TNext>(...params: [ | ||
...([timeout: number] | []), | ||
(lock: RWLockReader) => AsyncGenerator<T, TReturn, TNext> | ||
]): AsyncGenerator<T, TReturn, TNext>; | ||
withWriteG<T, TReturn, TNext>(...params: [ | ||
...([timeout: number] | []), | ||
(lock: RWLockReader) => AsyncGenerator<T, TReturn, TNext> | ||
]): AsyncGenerator<T, TReturn, TNext>; | ||
} | ||
export default RWLockReader; |
@@ -14,4 +14,12 @@ "use strict"; | ||
this._writerCount = 0; | ||
this.lock = new async_mutex_1.Mutex(); | ||
this._lock = new async_mutex_1.Mutex(); | ||
} | ||
lock(type, timeout) { | ||
switch (type) { | ||
case 'read': | ||
return this.read(timeout); | ||
case 'write': | ||
return this.write(timeout); | ||
} | ||
} | ||
read(timeout) { | ||
@@ -22,5 +30,5 @@ return async () => { | ||
if (readerCount === 1) { | ||
let lock = this.lock; | ||
let lock = this._lock; | ||
if (timeout != null) { | ||
lock = (0, async_mutex_1.withTimeout)(this.lock, timeout, new errors_1.ErrorAsyncLocksTimeout()); | ||
lock = (0, async_mutex_1.withTimeout)(this._lock, timeout, new errors_1.ErrorAsyncLocksTimeout()); | ||
} | ||
@@ -56,5 +64,5 @@ try { | ||
++this._writerCount; | ||
let lock = this.lock; | ||
let lock = this._lock; | ||
if (timeout != null) { | ||
lock = (0, async_mutex_1.withTimeout)(this.lock, timeout, new errors_1.ErrorAsyncLocksTimeout()); | ||
lock = (0, async_mutex_1.withTimeout)(this._lock, timeout, new errors_1.ErrorAsyncLocksTimeout()); | ||
} | ||
@@ -80,2 +88,5 @@ let release; | ||
} | ||
get count() { | ||
return this.readerCount + this.writerCount; | ||
} | ||
get readerCount() { | ||
@@ -88,3 +99,3 @@ return this._readerCount; | ||
isLocked() { | ||
return this.lock.isLocked(); | ||
return this._lock.isLocked(); | ||
} | ||
@@ -95,3 +106,3 @@ async waitForUnlock(timeout) { | ||
await Promise.race([ | ||
this.lock.waitForUnlock(), | ||
this._lock.waitForUnlock(), | ||
(0, utils_1.sleep)(timeout).then(() => { | ||
@@ -106,15 +117,41 @@ timedOut = true; | ||
else { | ||
await this.lock.waitForUnlock(); | ||
await this._lock.waitForUnlock(); | ||
} | ||
} | ||
async withReadF(f, timeout) { | ||
async withF(...params) { | ||
const type = params.shift(); | ||
switch (type) { | ||
case 'read': | ||
return this.withReadF(...params); | ||
case 'write': | ||
return this.withWriteF(...params); | ||
} | ||
} | ||
async withReadF(...params) { | ||
const f = params.pop(); | ||
const timeout = params[0]; | ||
return (0, resources_1.withF)([this.read(timeout)], ([lock]) => f(lock)); | ||
} | ||
async withWriteF(f, timeout) { | ||
async withWriteF(...params) { | ||
const f = params.pop(); | ||
const timeout = params[0]; | ||
return (0, resources_1.withF)([this.write(timeout)], ([lock]) => f(lock)); | ||
} | ||
withReadG(g, timeout) { | ||
withG(...params) { | ||
const type = params.shift(); | ||
switch (type) { | ||
case 'read': | ||
return this.withReadG(...params); | ||
case 'write': | ||
return this.withWriteG(...params); | ||
} | ||
} | ||
withReadG(...params) { | ||
const g = params.pop(); | ||
const timeout = params[0]; | ||
return (0, resources_1.withG)([this.read(timeout)], ([lock]) => g(lock)); | ||
} | ||
withWriteG(g, timeout) { | ||
withWriteG(...params) { | ||
const g = params.pop(); | ||
const timeout = params[0]; | ||
return (0, resources_1.withG)([this.write(timeout)], ([lock]) => g(lock)); | ||
@@ -121,0 +158,0 @@ } |
import type { MutexInterface } from 'async-mutex'; | ||
import type { ResourceAcquire } from '@matrixai/resources'; | ||
import type { Lockable } from './types'; | ||
import { Mutex } from 'async-mutex'; | ||
@@ -7,3 +8,3 @@ /** | ||
*/ | ||
declare class RWLockWriter { | ||
declare class RWLockWriter implements Lockable { | ||
protected readersLock: Mutex; | ||
@@ -15,4 +16,6 @@ protected writersLock: Mutex; | ||
protected _writerCount: number; | ||
lock(type: 'read' | 'write', timeout?: number): ResourceAcquire<RWLockWriter>; | ||
read(timeout?: number): ResourceAcquire<RWLockWriter>; | ||
write(timeout?: number): ResourceAcquire<RWLockWriter>; | ||
get count(): number; | ||
get readerCount(): number; | ||
@@ -22,7 +25,21 @@ get writerCount(): number; | ||
waitForUnlock(timeout?: number): Promise<void>; | ||
withReadF<T>(f: (lock: RWLockWriter) => Promise<T>, timeout?: number): Promise<T>; | ||
withWriteF<T>(f: (lock: RWLockWriter) => Promise<T>, timeout?: number): Promise<T>; | ||
withReadG<T, TReturn, TNext>(g: (lock: RWLockWriter) => AsyncGenerator<T, TReturn, TNext>, timeout?: number): AsyncGenerator<T, TReturn, TNext>; | ||
withWriteG<T, TReturn, TNext>(g: (lock: RWLockWriter) => AsyncGenerator<T, TReturn, TNext>, timeout?: number): AsyncGenerator<T, TReturn, TNext>; | ||
withF<T>(...params: [ | ||
...([type: 'read' | 'write', timeout: number] | [type: 'read' | 'write'] | []), | ||
(lock: RWLockWriter) => Promise<T> | ||
]): Promise<T>; | ||
withReadF<T>(...params: [...([timeout: number] | []), (lock: RWLockWriter) => Promise<T>]): Promise<T>; | ||
withWriteF<T>(...params: [...([timeout: number] | []), (lock: RWLockWriter) => Promise<T>]): Promise<T>; | ||
withG<T, TReturn, TNext>(...params: [ | ||
...([type: 'read' | 'write', timeout: number] | [type: 'read' | 'write'] | []), | ||
(lock: RWLockWriter) => AsyncGenerator<T, TReturn, TNext> | ||
]): AsyncGenerator<T, TReturn, TNext>; | ||
withReadG<T, TReturn, TNext>(...params: [ | ||
...([timeout: number] | []), | ||
(lock: RWLockWriter) => AsyncGenerator<T, TReturn, TNext> | ||
]): AsyncGenerator<T, TReturn, TNext>; | ||
withWriteG<T, TReturn, TNext>(...params: [ | ||
...([timeout: number] | []), | ||
(lock: RWLockWriter) => AsyncGenerator<T, TReturn, TNext> | ||
]): AsyncGenerator<T, TReturn, TNext>; | ||
} | ||
export default RWLockWriter; |
@@ -19,2 +19,10 @@ "use strict"; | ||
} | ||
lock(type, timeout) { | ||
switch (type) { | ||
case 'read': | ||
return this.read(timeout); | ||
case 'write': | ||
return this.write(timeout); | ||
} | ||
} | ||
read(timeout) { | ||
@@ -120,2 +128,5 @@ return async () => { | ||
} | ||
get count() { | ||
return this.readerCount + this.writerCount; | ||
} | ||
get readerCount() { | ||
@@ -153,12 +164,38 @@ return this._readerCount + this.readerCountBlocked; | ||
} | ||
async withReadF(f, timeout) { | ||
async withF(...params) { | ||
const type = params.shift(); | ||
switch (type) { | ||
case 'read': | ||
return this.withReadF(...params); | ||
case 'write': | ||
return this.withWriteF(...params); | ||
} | ||
} | ||
async withReadF(...params) { | ||
const f = params.pop(); | ||
const timeout = params[0]; | ||
return (0, resources_1.withF)([this.read(timeout)], ([lock]) => f(lock)); | ||
} | ||
async withWriteF(f, timeout) { | ||
async withWriteF(...params) { | ||
const f = params.pop(); | ||
const timeout = params[0]; | ||
return (0, resources_1.withF)([this.write(timeout)], ([lock]) => f(lock)); | ||
} | ||
withReadG(g, timeout) { | ||
withG(...params) { | ||
const type = params.shift(); | ||
switch (type) { | ||
case 'read': | ||
return this.withReadG(...params); | ||
case 'write': | ||
return this.withWriteG(...params); | ||
} | ||
} | ||
withReadG(...params) { | ||
const g = params.pop(); | ||
const timeout = params[0]; | ||
return (0, resources_1.withG)([this.read(timeout)], ([lock]) => g(lock)); | ||
} | ||
withWriteG(g, timeout) { | ||
withWriteG(...params) { | ||
const g = params.pop(); | ||
const timeout = params[0]; | ||
return (0, resources_1.withG)([this.write(timeout)], ([lock]) => g(lock)); | ||
@@ -165,0 +202,0 @@ } |
@@ -0,1 +1,2 @@ | ||
import type { ResourceAcquire } from '@matrixai/resources'; | ||
/** | ||
@@ -7,2 +8,16 @@ * Plain data dictionary | ||
}; | ||
export type { POJO }; | ||
/** | ||
* Any type that can be turned into a string | ||
*/ | ||
interface ToString { | ||
toString(): string; | ||
} | ||
interface Lockable { | ||
count: number; | ||
lock(...params: Array<unknown>): ResourceAcquire<Lockable>; | ||
isLocked(): boolean; | ||
waitForUnlock(timeout?: number): Promise<void>; | ||
withF<T>(...params: Array<unknown>): Promise<T>; | ||
withG<T, TReturn, TNext>(...params: Array<unknown>): AsyncGenerator<T, TReturn, TNext>; | ||
} | ||
export type { POJO, ToString, Lockable }; |
{ | ||
"name": "@matrixai/async-locks", | ||
"version": "2.1.1", | ||
"version": "2.2.0", | ||
"author": "Roger Qiu", | ||
@@ -5,0 +5,0 @@ "description": "Asynchronous locking utilities", |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
59374
27
780