Skip to content

Instantly share code, notes, and snippets.

@kobzarvs
Created September 11, 2023 14:25
Show Gist options
  • Save kobzarvs/7ad249b1d37376bb3ded7861c781ab98 to your computer and use it in GitHub Desktop.
Save kobzarvs/7ad249b1d37376bb3ded7861c781ab98 to your computer and use it in GitHub Desktop.
export class AsyncTaskSeq {
last = Promise.resolve();
add(task: () => Promise<void>) {
const sync = this.last;
this.last = new Promise(async (resolve, reject) => {
try {
await sync;
await task();
resolve();
} catch (e) {
reject(e);
}
});
}
}
interface LinkedResolver {
next: LinkedResolver | null;
(): void;
}
class AsyncLinkedTaskPool {
private count = 0;
private head: LinkedResolver | null = null;
private tail: LinkedResolver | null = null;
constructor(private readonly size = 3) {
}
add(task: () => Promise<void>) {
const wrapped = async () => {
await this.acquire();
try {
await task();
} finally {
this.release();
}
};
wrapped();
}
private acquire(): Promise<void> {
return new Promise<void>((resolve) => {
const resolver = resolve as LinkedResolver;
resolver.next = null;
if (!this.tail) {
this.tail = this.head = resolver;
} else {
this.tail = this.tail.next = resolver;
}
this.dispatch();
});
}
private release(): void {
this.count--;
this.dispatch();
}
private dispatch(): void {
if (this.count < this.size && this.head) {
this.count++;
const resolve = this.head;
if (this.head === this.tail) {
this.head = this.tail = null;
} else {
this.head = this.head.next;
}
resolve();
}
}
}
interface Idle extends Promise<void> {
resolve: () => void;
}
export class AsyncTaskPool {
size = 3;
count = 0;
private idle?: Idle | null = null;
constructor(size = 3) {
this.size = size;
}
private getIdle(): Idle {
let resolve: () => void;
const idle = new Promise<void>(rs => resolve = rs) as Idle;
idle.resolve = resolve!;
return idle;
}
async add(task: () => Promise<void>) {
while (this.count === this.size) {
await this.idle;
}
if (!this.idle) {
this.idle = this.getIdle();
}
this.count++;
try {
await task();
} catch(e) {
throw e;
} finally {
this.count--;
this.idle?.resolve();
this.idle = null;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment