I wrote a class CountDownLatchContainer
it has a await()
method, that waits on all CountDownLatches. Everything is working fine.
public final class CountDownLatchContainer
{
private final Set<CountDownLatch> countDowns;
public CountDownLatchContainer(List<CountDownLatch> countDowns)
{
this.countDowns = new HashSet<CountDownLatch>(countDowns);
}
public void await() throws InterruptedException
{
for (CountDownLatch count : countDowns)
count.await();
}
}
For the sake of science and art (:D), I wanted to extend the functionality and add the public boolean await(long timeout, TimeUnit unit)
from the CountDownLatch
class.
I want each countdown latch to have the same timeout and the method overall just to block for the number of timeout
TimeUnits. I have difficulties achieving that. What I have is:
public boolean await(long timeout, TimeUnit unit) throws InterruptedException
{
boolean success = true;
for (CountDownLatch count : countDowns)
success &= count.await(timeout / countDowns.size(), unit);
return success;
}
So, the overall time out is taken care of, but each count down has just a percentage of the overall time.
So how can I give the single latches the same amount of time as specified in the method parameter without execeeding the total time?
Here a visualization. Thx to hexafraction for the ascii art inspiration.
|-----------------------------|
Total
|-----------------------------|
L1
|-----------------------------|
L2
|-----------------------------|
Work by awaiting each latch and then seeing how much time remains.
Start by awaiting the first latch for the original time. Note how long it actually took. Remaining time is set to the total minus time took. Now, await the next latch with a limit of the remaining time. Subtract actual. Continue until all latches are awaited or remaining time reaches 0(due to a latch timing out in its remaining time)
|-----------------------------|
Total
|------|----------------------|
L1 Remaining(1)
|------|---------|------------|
L1 L2 Remaining(2)
and so on... await l1 for total, l2 for remaining(1), etc, etc
Another approach is to timeslice the operation into slices, such as 1 msec each. Loop the latches(marking them as used/removing them via an iterator of a mutable copy of the set could be good) and await for the slice length, until either all latches are released or the time is reached.