This barrier is used when we don't know how many events are we waiting on
from the start. Instead we have a set of task ids, and each of those will,
at some point of time, give the information about how many events from it
should we expect. Barrier will be waiting for all the tasks to notify it
about that number of events, and than it will also wait for all the events
requirePermits() corresponds to task notifying us how many events from it
to expect, and releasePermits() notifies us about events happening.
This class is currently used during preparation of aggregators.
User must follow this protocol for concurrent access:
(1) an object instance is constructed
(2) arbitrarily many times
(2a) concurrent calls to requirePermits(), releasePermits() and
waitForRequiredPermits() are issued
(2b) waitForRequiredPermits() returns
Note that the next cycle of calls to requirePermits() or releasePermits()
cannot start until the previous call to waitForRequiredPermits()
Methods of this class are thread-safe.