Skip to content
File

Blob: src/worker/git/pack/indexer/resolve/dependencies.ts

typescript83 lines
1import type { PackEntryTable } from "../types";
2 
3export interface InPackDependencyQueue {
4 waitHeadByBase: Int32Array;
5 nextWaitByEntry: Int32Array;
6 registeredBaseByEntry: Int32Array;
7}
8 
9export function createInPackDependencyQueue(objectCount: number): InPackDependencyQueue {
10 return {
11 waitHeadByBase: new Int32Array(objectCount).fill(-1),
12 nextWaitByEntry: new Int32Array(objectCount).fill(-1),
13 registeredBaseByEntry: new Int32Array(objectCount).fill(-1),
14 };
15}
16 
17export function extendDeadlineChain(
18 deadlines: Uint32Array,
19 baseIndexArr: Int32Array,
20 startIndex: number,
21 neededUntil: number
22): void {
23 let cur = startIndex;
24 for (let guard = 0; cur >= 0 && guard < baseIndexArr.length; guard++) {
25 if (deadlines[cur] < neededUntil) {
26 deadlines[cur] = neededUntil;
27 }
28 cur = baseIndexArr[cur];
29 }
30}
31 
32export function registerInPackDependency(
33 queue: InPackDependencyQueue,
34 baseIndexArr: Int32Array,
35 entryIndex: number
36): void {
37 const baseIndex = baseIndexArr[entryIndex];
38 if (baseIndex < 0) return;
39 if (queue.registeredBaseByEntry[entryIndex] === baseIndex) return;
40 
41 // Every delta has exactly one in-pack base edge once `baseIndexArr` is set.
42 // Recording that edge lets the resolver wake dependents in O(children) when
43 // a late base finally resolves instead of rescanning the whole deferred set.
44 queue.nextWaitByEntry[entryIndex] = queue.waitHeadByBase[baseIndex];
45 queue.waitHeadByBase[baseIndex] = entryIndex;
46 queue.registeredBaseByEntry[entryIndex] = baseIndex;
47}
48 
49export function enqueueReadyDeferred(
50 readyDeferred: number[],
51 deferredQueued: Uint8Array,
52 table: PackEntryTable,
53 baseIndexArr: Int32Array,
54 index: number
55): void {
56 if (deferredQueued[index] || table.resolved[index]) return;
57 const bi = baseIndexArr[index];
58 if (bi < 0 || !table.resolved[bi]) return;
59 deferredQueued[index] = 1;
60 readyDeferred.push(index);
61}
62 
63export function promoteReadyInPackDependents(
64 queue: InPackDependencyQueue,
65 resolvedIndex: number,
66 readyDeferred: number[],
67 deferredQueued: Uint8Array,
68 table: PackEntryTable,
69 baseIndexArr: Int32Array
70): void {
71 let waitingEntry = queue.waitHeadByBase[resolvedIndex];
72 if (waitingEntry < 0) return;
73 
74 queue.waitHeadByBase[resolvedIndex] = -1;
75 while (waitingEntry >= 0) {
76 const nextWaitingEntry = queue.nextWaitByEntry[waitingEntry];
77 queue.nextWaitByEntry[waitingEntry] = -1;
78 queue.registeredBaseByEntry[waitingEntry] = -1;
79 enqueueReadyDeferred(readyDeferred, deferredQueued, table, baseIndexArr, waitingEntry);
80 waitingEntry = nextWaitingEntry;
81 }
82}