Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 | 1x 56x 56x 56x 56x 56x 56x 56x 56x 56x 56x 7x 7x 7x 56x 56x 56x 56x 56x 56x 56x 56x 56x 56x 56x 56x 56x 56x 56x 56x 56x 56x 56x 56x 56x 56x 56x 56x 56x 56x 56x 56x 56x 56x 56x 56x 56x 56x 55x 55x 56x 56x | const uniqueCounterScopes = new WeakMap<object, Promise<void>>()
async function runEnsureUniqueCounterValue<T>({
initialValue,
isTaken,
reserve,
nextValue,
}: {
initialValue: T
isTaken: (candidate: T) => Promise<boolean> | boolean
reserve: (candidate: T) => void
nextValue: (counter: number) => T
}): Promise<T> {
let candidate = initialValue
let counter = 1
while (await isTaken(candidate)) {
candidate = nextValue(counter)
counter += 1
}
reserve(candidate)
return candidate
}
export async function ensureUniqueCounterValue<T>({
initialValue,
isTaken,
reserve,
nextValue,
scope,
}: {
initialValue: T
isTaken: (candidate: T) => Promise<boolean> | boolean
reserve: (candidate: T) => void
nextValue: (counter: number) => T
scope?: object
}): Promise<T> {
if (scope == null) {
return await runEnsureUniqueCounterValue({
initialValue,
isTaken,
reserve,
nextValue,
})
}
const previous = uniqueCounterScopes.get(scope) ?? Promise.resolve()
let releaseScope: (() => void) | undefined
const pendingScope = new Promise<void>((resolve) => {
releaseScope = resolve
})
const currentScope = previous
.catch(() => undefined)
.then(async () => {
await pendingScope
})
uniqueCounterScopes.set(scope, currentScope)
await previous.catch(() => undefined)
try {
return await runEnsureUniqueCounterValue({
initialValue,
isTaken,
reserve,
nextValue,
})
} finally {
releaseScope?.()
if (uniqueCounterScopes.get(scope) === currentScope) {
uniqueCounterScopes.delete(scope)
}
}
}
|