Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
jokester committed Apr 5, 2024
1 parent f96c3e0 commit 40314d7
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 18 deletions.
3 changes: 3 additions & 0 deletions src/concurrency/locks/lockable.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
describe('ResourcePool lock', () => {
it.skip('');
});
15 changes: 6 additions & 9 deletions src/concurrency/locks/lockable.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
import { ResourcePool } from '../resource-pool';

export class LockableError extends Error {
static A = class L2 extends LockableError {};
}

interface AutoClosable {
close(): void;
[Symbol.dispose](): void;
}

export abstract class Mutex<Resource extends object | true> {
abstract lock(): AutoClosable;
abstract unlock(): void;
abstract tryLock(): boolean;
export interface Lease<T> {
value: T;
// close(): Promise<void>;
[Symbol.asyncDispose](): Promise<void>;
}
35 changes: 26 additions & 9 deletions src/concurrency/resource-pool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
* - NOT supported: replace / refresh / timeout of tasks
*/
import { wait } from './timing';
import { Lease } from './locks/lockable';
import { lazyThenable } from './lazy-thenable';

export class ResourcePool<T> {
// can be used as a mutex
Expand Down Expand Up @@ -38,16 +40,11 @@ export class ResourcePool<T> {
}

async use<R>(task: (res: T) => R): Promise<Awaited<R>> {
const r = await this.borrow();
try {
return await task(r);
} finally {
this.resources.push(r);
this.balance();
}
await using lease = await this.borrow();
return await task(lease.value);
}

tryUse<R>(task: (res: T | null) => R): R | Promise<R> {
tryUse<R>(task: (res: T | null) => R): R | Promise<Awaited<R>> {
if (/** some resource is immediately available */ this.freeCount > 0) {
return this.use(task);
} else {
Expand Down Expand Up @@ -88,13 +85,33 @@ export class ResourcePool<T> {
}
}

private borrow(): Promise<T> {
async borrow(timeout?: number): Promise<Lease<T>> {
const v = await this._borrow();

const _return = lazyThenable(async () => {
this._return(v);
});

return {
value: v,
async [Symbol.asyncDispose]() {
await _return;
},
};
}

private _borrow(): Promise<T> {
return new Promise<T>((f) => {
this.consumers.push(f);
this.balance();
});
}

private _return(value: T): void {
this.resources.push(value);
this.balance();
}

private balance(): void {
while (this.resources.length && this.consumers.length) {
const r = this.resources.shift()!;

Check warning on line 117 in src/concurrency/resource-pool.ts

View workflow job for this annotation

GitHub Actions / check

Forbidden non-null assertion
Expand Down

0 comments on commit 40314d7

Please sign in to comment.