Last active
January 24, 2024 09:46
-
-
Save mjy9088/9d39dfd381b19d185445478f433ba249 to your computer and use it in GitHub Desktop.
Typescript CriticalSection
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
interface Pending { | |
resolve: (value: any) => void; | |
reject: (error: any) => void; | |
criticalSection: () => Promise<unknown>; | |
} | |
export function criticalSection(): <T>( | |
criticalSection: () => Promise<T> | |
) => Promise<T> { | |
const pending: Pending[] = []; | |
let running = false; | |
return <T>(criticalSection: () => Promise<T>) => { | |
return new Promise<T>((resolve, reject) => { | |
(async () => { | |
pending.push({ criticalSection, reject, resolve }); | |
if (!running) { | |
running = true; | |
while (pending.length) { | |
const { criticalSection, reject, resolve } = pending.shift()!; | |
try { | |
resolve(await criticalSection()); | |
} catch (err) { | |
reject(err); | |
} | |
} | |
running = false; | |
} | |
})(); | |
}); | |
}; | |
} |
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
import { criticalSection } from "./criticalSection.ts"; | |
function waitFor(ms: number) { | |
return new Promise<void>((resolve) => { | |
setTimeout(() => resolve(), ms); | |
}); | |
} | |
const cs = criticalSection(); | |
(async () => { | |
await Promise.all([ | |
(async () => { | |
await waitFor(1000); | |
console.log("1000"); | |
await cs(async () => { | |
console.log("1000"); | |
await waitFor(1000); | |
}); | |
console.log("2000"); | |
})(), | |
(async () => { | |
await waitFor(1001); | |
console.log("1001"); | |
await cs(async () => { | |
console.log("2000"); | |
await waitFor(1000); | |
}); | |
console.log("3000"); | |
})(), | |
]); | |
function makeTestCriticalSection(name: string, ms: number) { | |
return async () => { | |
console.log(`${name} start`); | |
await waitFor(ms); | |
console.log(`${name} end`); | |
}; | |
} | |
setTimeout(() => cs(makeTestCriticalSection("first", 500)), 500); | |
setTimeout(() => cs(makeTestCriticalSection("second", 500)), 501); | |
})(); | |
/* | |
result: | |
1000 | |
1000 | |
1001 | |
2000 | |
2000 | |
3000 | |
first start | |
first end | |
second start | |
second end | |
*/ |
Yte3588
#jiiibejwjskakakka
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
****
](``)