ARTICLE AD BOX
We use multiple worker-processes, which prepare data to be used by a special shared processor. The preparation is CPU-intensive, so we start many of them in parallel. The shared processor has large, but finite capacity.
Each worker operates in cycles: processing a batch of items adding it to its superbatch, checks if the shared processor can take its superbatch now, and, if it cannot not, goes on to process another batch of items adding it to its superbatch.
This goes on until a worker's superbatch reaches the shared processor's maximum capacity (N). When the size of a worker's superbatch reaches N, the worker blocks waiting for the resource to free up.
We want workers with smaller superbatches (between 1 and N) to be able to be able to check -- without blocking -- whether the shared processor can take them, and use it right away, if possible.
I thought, we'd be able to use multiprocessing.Semaphore for this, but semaphores are boolean: yes or no. You can create N semaphores for workers to take one or more, but it is impossible to take more than one atomically, and you end up with a deadlock where two heavy workers each grab a couple, preventing each other from running.
We don't need it to be fair -- there is no need to ensure FIFO.
We prefer the largest workers (those whose superbatches already reached the full N) to have priority over the lightweights still building up theirs.
Yet, if a lightweight happens to be checking, and the shared processor can accommodate it, because it is only processing another lightweight, the new lightweight -- the largest among them, that fits -- should be allowed in.
Is this not a known pattern? Is there, perhaps, an existing implementation already?
