docs: @Override
      @FFDCIgnore(value = { RejectedExecutionException.class })
      public <T> T invokeAny(Collection<? extends Callable<T>> tasks, PolicyTaskCallback[] callbacks, long timeout,
                             TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
          int taskCount = tasks.size();
          long stop = System.nanoTime() + unit.toNanos(timeout);
          long qWait, remaining;
  
          if (taskCount == 0) // JavaDoc doesn't specify what to do in this case. Match behavior of untimed invokeAny.
              throw new IllegalArgumentException();
  
          InvokeAnyLatch latch = new InvokeAnyLatch(taskCount);
          ArrayList<PolicyTaskFutureImpl<T>> futures = new ArrayList<PolicyTaskFutureImpl<T>>(taskCount);
          try {
              // create futures in advance, which gives the callback an opportunity to reject
              int t = 0;
              for (Callable<T> task : tasks) {
                  remaining = stop - System.nanoTime();
                  PolicyTaskCallback callback = callbacks == null ? null : callbacks[t++];
                  PolicyExecutorImpl executor = callback == null ? this : (PolicyExecutorImpl) callback.getExecutor(this);
                  long startTimeoutNS = callback == null ? startTimeout : callback.getStartTimeout(executor.startTimeout);
                  PolicyTaskFutureImpl<T> taskFuture = new PolicyTaskFutureImpl<T>(executor, task, callback, startTimeoutNS, latch);
                  futures.add(taskFuture);
                  if (remaining <= 0)
                      throw new RejectedExecutionException(Tr.formatMessage(tc, "CWWKE1204.unable.to.invoke", taskFuture.getIdentifier(),
                                                                            taskCount - futures.size(), taskCount, timeout, unit));
              }
  
              // enqueue all tasks
              for (PolicyTaskFutureImpl<T> taskFuture : futures) {
                  remaining = stop - System.nanoTime();
  
                  // check if done before enqueuing more tasks
                  if (latch.getCount() == 0)
                      break;
  
                  if (remaining <= 0)
                      throw new RejectedExecutionException(Tr.formatMessage(tc, "CWWKE1204.unable.to.invoke", taskFuture.getIdentifier(),
                                                                            taskCount - futures.size(), taskCount, timeout, unit));
                  qWait = taskFuture.executor.maxWaitForEnqueueNS.get();
                  taskFuture.executor.enqueue(taskFuture,
                                              qWait < remaining ? qWait : remaining, // limit waiting to lesser of maxWaitForEnqueue and remaining time
                                              false); // never run on the current thread because it would prevent timeout
              }
  
              // wait for completion
              remaining = stop - System.nanoTime();
              return latch.await(remaining < 0 ? 0 : remaining, futures);
          } catch (RejectedExecutionException x) {
              if (x.getCause() instanceof InterruptedException)
                  throw (InterruptedException) x.getCause();
              else
                  throw x;
          } finally {
              for (Future<?> f : futures)
                  f.cancel(true);
          }
      }