MCPcopy Create free account
hub / github.com/microsoft/vscode-cpptools / accumulator

Function accumulator

Extension/src/Utility/Async/iterators.ts:77–135  ·  view source on GitHub ↗
(...iterables: Some<T>[])

Source from the content-addressed store, hash-verified

75};
76
77export function accumulator<T>(...iterables: Some<T>[]): AsynchIterable<T> {
78 const iterators = new Map<number, Promise<Cursor<T>>>();
79 let completeWhenEmpty = iterables.length > 0; // if we are given any items, they we auto-complete when we run out (so an add after the last item is yielded will throw)
80 const signal = new Signal<boolean>();
81
82 const result = combiner(iterables) as unknown as AsynchIterable<T>;
83 result.add = (...iterables: (Some<T> | undefined | Promise<undefined | T>)[]) => {
84 for (const iterable of iterables) {
85 iterators.set(iterators.size + 1, awaitNext({ identity: iterators.size + 1, iterator: asyncOf(iterable)[Symbol.asyncIterator]() }));
86 }
87 signal.resolve(true);
88 };
89
90 result.autoComplete = (shouldAutocomplete: boolean) => { completeWhenEmpty = shouldAutocomplete; return result; };
91 result.complete = () => signal.dispose(completeWhenEmpty = true);
92 result.reiterable = () => reiterable(result);
93
94 return result;
95
96 async function awaitNext(element: Cursor<T>): Promise<Cursor<T>> {
97 element.result = undefined; // drop the previous result before awaiting the next
98 element.result = await element.iterator.next();
99 return element;
100 }
101
102 async function* combiner(iterables: Some<T>[]) {
103 iterables.forEach((iterable, index) => iterators.set(index, awaitNext({ identity: index, iterator: asyncOf(iterable)[Symbol.asyncIterator]() })));
104
105 // Loop until all iterators are done, removing them as they complete
106 do {
107 if (!iterators.size && !completeWhenEmpty) {
108 await signal; // wait for a new item to be added, or for the complete signal
109 }
110
111 while (iterators.size) {
112 const element = await race([...iterators.values()]);
113
114 // Is that iterator done?
115 if (element.result!.done) {
116 iterators.delete(element.identity);
117 continue;
118 }
119
120 // Yield the result from the iterator, and await the next item
121 const { value } = element.result!;
122 iterators.set(element.identity, awaitNext(element));
123 if (value !== undefined && value !== null) {
124 yield value;
125 }
126
127 }
128
129 } while (!completeWhenEmpty);
130 signal.dispose(false);
131
132 // prevent any more iterators from being added
133 result.add = () => { throw new Error('AsyncIterable is finished'); };
134 }

Callers 4

FastFinderClass · 0.90
scanFolderFunction · 0.90
FinderClass · 0.90

Calls 7

resolveMethod · 0.95
disposeMethod · 0.95
combinerFunction · 0.85
awaitNextFunction · 0.85
asyncOfFunction · 0.85
reiterableFunction · 0.85
setMethod · 0.45

Tested by

no test coverage detected