/*
* Copyright 2014 WANdisco
*
* WANdisco licenses this file to you under the Apache License,
* version 2.0 (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package c5db;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.SettableFuture;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
/**
* Utilities for running concurrency tests.
*/
public class ConcurrencyTestUtil {
public static void runAConcurrencyTestSeveralTimes(int numThreads, int numAttempts, ConcurrencyTest test)
throws Exception {
final ExecutorService taskSubmitter = Executors.newFixedThreadPool(numThreads);
for (int attempt = 0; attempt < numAttempts; attempt++) {
test.run(numThreads * 2, taskSubmitter);
}
taskSubmitter.shutdown();
taskSubmitter.awaitTermination(10, TimeUnit.SECONDS);
}
public static void runNTimesAndWaitForAllToComplete(int nTimes, ExecutorService executor,
IndexedExceptionThrowingRunnable runnable) throws Exception {
final List<ListenableFuture<Boolean>> completionFutureList = new ArrayList<>(nTimes);
for (int i = 0; i < nTimes; i++) {
completionFutureList.add(
runAndReturnCompletionFuture(executor, runnable, i));
}
waitForAll(completionFutureList);
}
public static void runNTimesAndWaitForAllToComplete(int nTimes, ExecutorService executor,
ExceptionThrowingRunnable runnable) throws Exception {
runNTimesAndWaitForAllToComplete(nTimes, executor, (int ignore) -> runnable.run());
}
private static ListenableFuture<Boolean> runAndReturnCompletionFuture(ExecutorService executor,
IndexedExceptionThrowingRunnable runnable,
int invocationIndex) {
final SettableFuture<Boolean> setWhenFinished = SettableFuture.create();
executor.execute(() -> {
try {
runnable.run(invocationIndex);
setWhenFinished.set(true);
} catch (Throwable t) {
setWhenFinished.setException(t);
}
});
return setWhenFinished;
}
private static void waitForAll(List<ListenableFuture<Boolean>> futures) throws Exception {
Futures.allAsList(futures).get();
}
public interface ConcurrencyTest {
void run(int degreeOfConcurrency, ExecutorService executorService) throws Exception;
}
public interface IndexedExceptionThrowingRunnable {
void run(int indexIdentifyingThisInvocation) throws Exception;
}
public interface ExceptionThrowingRunnable {
void run() throws Exception;
}
}