MultiResultSyncPoint.java

  1. /**
  2.  *
  3.  * Copyright 2021-2024 Guus der Kinderen
  4.  *
  5.  * Licensed under the Apache License, Version 2.0 (the "License");
  6.  * you may not use this file except in compliance with the License.
  7.  * You may obtain a copy of the License at
  8.  *
  9.  *     http://www.apache.org/licenses/LICENSE-2.0
  10.  *
  11.  * Unless required by applicable law or agreed to in writing, software
  12.  * distributed under the License is distributed on an "AS IS" BASIS,
  13.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14.  * See the License for the specific language governing permissions and
  15.  * limitations under the License.
  16.  */
  17. package org.igniterealtime.smack.inttest.util;

  18. import java.util.ArrayList;
  19. import java.util.List;
  20. import java.util.concurrent.TimeoutException;

  21. import org.jivesoftware.smack.util.Objects;

  22. public class MultiResultSyncPoint<R, E extends Exception> {

  23.     private final List<R> results;
  24.     private E exception;
  25.     private final int expectedResultCount;

  26.     public MultiResultSyncPoint(int expectedResultCount) {
  27.         this.expectedResultCount = expectedResultCount;
  28.         this.results = new ArrayList<>(expectedResultCount);
  29.     }

  30.     public synchronized List<R> waitForResults(long timeout) throws E, InterruptedException, TimeoutException {
  31.         return waitForResults(timeout, null);
  32.     }

  33.     public synchronized List<R> waitForResults(long timeout, String timeoutMessage) throws E, InterruptedException, TimeoutException {
  34.         long now = System.currentTimeMillis();
  35.         final long deadline = now + timeout;
  36.         while (results.size() < expectedResultCount && exception == null && now < deadline) {
  37.             wait(deadline - now);
  38.             now = System.currentTimeMillis();
  39.         }
  40.         if (now >= deadline) {
  41.             StringBuilder sb = new StringBuilder();
  42.             if (timeoutMessage != null) {
  43.                 sb.append(timeoutMessage).append(". ");
  44.             }
  45.             sb.append("MultiResultSyncPoint timeout waiting " + timeout + " ms. Got " + results.size() + " results of " + expectedResultCount + " results");

  46.             throw new TimeoutException(sb.toString());
  47.         }
  48.         if (exception != null) throw exception;
  49.         return new ArrayList<>(results);
  50.     }

  51.     public synchronized void signal(R result) {
  52.         this.results.add(Objects.requireNonNull(result));
  53.         if (expectedResultCount <= results.size()) {
  54.             notifyAll();
  55.         }
  56.     }

  57.     public synchronized void signal(E exception) {
  58.         this.exception = Objects.requireNonNull(exception);
  59.         notifyAll();
  60.     }
  61. }