@@ -18,10 +18,39 @@ def get_exe_path(exe):
1818return path
1919
2020
21- def iter_buffer (iterable , amount ):
21+ def iter_buffer (generator , amount ):
22+ """Iterate with buffering
23+
24+ This is a utility function that's useful for asynchronous processing.
25+ It buffers the elements of the given generator to earn time for items
26+ to do their processing.
27+
28+ The argument is assumed to be a generator (although it would work with
29+ any iterable) that generates items which start their processing in
30+ the background at the time they are generated. And the caller is assumed
31+ to consume those items when their processing is complete.
32+
33+ This function is going to maintain a FIFO buffer up to the given size.
34+ It'd start with an empty buffer (memo), buffer all of the generated items
35+ until the buffer is full or the generator starts generating None, then
36+ start adding items to the end yielding from the beginning of the buffer,
37+ and finally yield the ones that are left in the buffer after the generator
38+ is consumed.
39+
40+ The buffering is short-cut when the generator generates None as the next
41+ item. This is a useful feature when the caller needs to wait for some
42+ item in the buffer to complete. The generated None's are never yielded
43+ to the caller.
44+
45+ Note that this procedure does not support out-of-order consumption of
46+ the items. The caller would always have to wait for the first yielded
47+ item to be done with its processing. While the caller is waiting,
48+ another item in the buffer may become ready, but we wouldn't even know.
49+ This is how this function remains very simple.
50+ """
2251assert amount > 1
2352memo = []
24- for elem in iterable :
53+ for elem in generator :
2554if elem is not None :
2655memo .append (elem )
2756if len (memo ) < amount :
0 commit comments