Skip to content

Commit c6d230c

Browse files
committed
Initial functional commit.
There seems to be a problem with my `Promise.any` polyfill library that needs fixing.
1 parent 54771b2 commit c6d230c

File tree

3 files changed

+149
-1
lines changed

3 files changed

+149
-1
lines changed

ts/main.ts

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,35 @@
1212
* @since v0.1.0
1313
*/
1414

15-
// export { ClassName } from "./class-location";
15+
export { Semaphore } from "./semaphore";
16+
export { SemaphoreLock } from "./semaphore-lock";
17+
18+
// @ts-ignore
19+
import { Semaphore } from "./semaphore";
20+
// @ts-ignore
21+
import { SemaphoreLock } from "./semaphore-lock";
22+
23+
export async function main(): Promise<void> {
24+
25+
let semaphore: Semaphore = new Semaphore(3);
26+
27+
let count: number = 0;
28+
let locks: SemaphoreLock[] = [];
29+
30+
for (let i: number = 0; i < 5; i++) {
31+
32+
let lock: SemaphoreLock = await semaphore.getLock();
33+
34+
locks.push(lock);
35+
console.log(`Got lock #${++count} (id: '${lock.getID()}')`);
36+
37+
}
38+
39+
console.log(`For loop finished...`);
40+
41+
console.log(`Relinquishing lock #1...`);
42+
locks[0].relinquish();
43+
44+
}
45+
46+
main().catch((e: any) => console.error(e));

ts/semaphore-lock.ts

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/*
2+
* Created by Trevor Sears <trevor@trevorsears.com> (https://trevorsears.com/).
3+
* 3:09 PM -- September 09, 2021.
4+
* Project: @jsdsl/semaphore
5+
*/
6+
7+
export class SemaphoreLock {
8+
9+
protected readonly id: string;
10+
11+
protected relinquishmentPromise: Promise<string>;
12+
13+
protected relinquisherFunction!: () => void;
14+
15+
public constructor(id: string) {
16+
17+
this.id = id;
18+
19+
this.relinquishmentPromise = new Promise<string>((resolve: (id: string) => void): void => {
20+
21+
this.relinquisherFunction = (): void => resolve(this.id);
22+
23+
});
24+
25+
}
26+
27+
public getID(): string {
28+
29+
return this.id;
30+
31+
}
32+
33+
public relinquish(): void {
34+
35+
this.relinquisherFunction();
36+
37+
}
38+
39+
public onRelinquish(): Promise<string> {
40+
41+
return this.relinquishmentPromise;
42+
43+
}
44+
45+
}

ts/semaphore.ts

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
/*
2+
* Created by Trevor Sears <trevor@trevorsears.com> (https://trevorsears.com/).
3+
* 3:09 PM -- September 09, 2021.
4+
* Project: @jsdsl/semaphore
5+
*/
6+
7+
import "promise-any-polyfill";
8+
import crypto from "crypto";
9+
import { SemaphoreLock } from "./semaphore-lock";
10+
11+
type OutstandingLockMap = {
12+
13+
[id: string]: Promise<string>
14+
15+
}
16+
17+
export class Semaphore {
18+
19+
protected readonly maxLockCount: number;
20+
21+
protected outstandingLocks: OutstandingLockMap;
22+
23+
public constructor(maxLockCount: number) {
24+
25+
this.maxLockCount = maxLockCount;
26+
this.outstandingLocks = {};
27+
28+
}
29+
30+
public async getLock(): Promise<SemaphoreLock> {
31+
32+
// While we are at or (hopefully not) above capacity...
33+
while (this.getLockCount() >= this.getMaximumLockCount()) {
34+
35+
console.log(`Waiting to remove promise...`);
36+
37+
let resolution: any = await Promise.any(Object.values(this.outstandingLocks))
38+
39+
console.log(`resolution: ${resolution}`);
40+
41+
// Remove the first resolved promise that we find.
42+
delete this.outstandingLocks[resolution];
43+
44+
console.log(`...found promise to remove!`);
45+
46+
}
47+
48+
console.log(`Generating new lock.`);
49+
50+
let id: string = crypto.randomBytes(16).toString("hex");
51+
52+
let lock: SemaphoreLock = new SemaphoreLock(id);
53+
54+
this.outstandingLocks[id] = lock.onRelinquish();
55+
56+
return lock;
57+
58+
}
59+
60+
public getLockCount(): number {
61+
62+
return Object.keys(this.outstandingLocks).length;
63+
64+
}
65+
66+
public getMaximumLockCount(): number {
67+
68+
return this.maxLockCount;
69+
70+
}
71+
72+
}

0 commit comments

Comments
 (0)