Created
September 11, 2023 14:25
-
-
Save kobzarvs/7ad249b1d37376bb3ded7861c781ab98 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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