mirror of
https://github.com/tommyskeff/futur4j.git
synced 2026-03-19 02:01:22 +00:00
141 lines
4.0 KiB
Java
141 lines
4.0 KiB
Java
package dev.tommyjs.futur.stress;
|
|
|
|
import dev.tommyjs.futur.promise.CompletablePromise;
|
|
import dev.tommyjs.futur.promise.PromiseFactory;
|
|
import dev.tommyjs.futur.util.ConcurrentResultArray;
|
|
import org.openjdk.jcstress.annotations.*;
|
|
import org.openjdk.jcstress.infra.results.I_Result;
|
|
import org.openjdk.jcstress.infra.results.L_Result;
|
|
import org.slf4j.LoggerFactory;
|
|
|
|
import java.util.concurrent.Executors;
|
|
import java.util.concurrent.atomic.AtomicInteger;
|
|
|
|
public class FuturStress {
|
|
|
|
private static PromiseFactory factory() {
|
|
return PromiseFactory.of(
|
|
LoggerFactory.getLogger(FuturStress.class),
|
|
Executors.newScheduledThreadPool(1)
|
|
);
|
|
}
|
|
|
|
@JCStressTest
|
|
@Outcome(id = "1", expect = Expect.ACCEPTABLE, desc = "Listener called exactly once")
|
|
@Outcome(expect = Expect.FORBIDDEN, desc = "Unexpected call count")
|
|
@State
|
|
public static class ListenerVersusComplete {
|
|
|
|
final CompletablePromise<Integer> promise;
|
|
final AtomicInteger callCount = new AtomicInteger();
|
|
|
|
public ListenerVersusComplete() {
|
|
promise = factory().unresolved();
|
|
promise.addDirectListener(v -> {});
|
|
}
|
|
|
|
@Actor
|
|
public void adder() {
|
|
promise.addDirectListener(v -> callCount.incrementAndGet());
|
|
}
|
|
|
|
@Actor
|
|
public void completer() {
|
|
promise.complete(42);
|
|
}
|
|
|
|
@Arbiter
|
|
public void arbiter(I_Result r) {
|
|
r.r1 = callCount.get();
|
|
}
|
|
|
|
}
|
|
|
|
@JCStressTest
|
|
@Outcome(id = "1", expect = Expect.ACCEPTABLE, desc = "Listener called exactly once")
|
|
@Outcome(expect = Expect.FORBIDDEN, desc = "Unexpected call count")
|
|
@State
|
|
public static class ConcurrentComplete {
|
|
|
|
final CompletablePromise<Integer> promise;
|
|
final AtomicInteger callCount = new AtomicInteger();
|
|
|
|
public ConcurrentComplete() {
|
|
promise = factory().unresolved();
|
|
promise.addDirectListener(v -> callCount.incrementAndGet());
|
|
}
|
|
|
|
@Actor
|
|
public void completer1() {
|
|
promise.complete(1);
|
|
}
|
|
|
|
@Actor
|
|
public void completer2() {
|
|
promise.complete(2);
|
|
}
|
|
|
|
@Arbiter
|
|
public void arbiter(I_Result r) {
|
|
r.r1 = callCount.get();
|
|
}
|
|
|
|
}
|
|
|
|
@JCStressTest
|
|
@Outcome(id = "2", expect = Expect.ACCEPTABLE, desc = "Both listeners called exactly once")
|
|
@Outcome(expect = Expect.FORBIDDEN, desc = "Unexpected call count")
|
|
@State
|
|
public static class ConcurrentListenerAdders {
|
|
|
|
final CompletablePromise<Integer> promise;
|
|
final AtomicInteger callCount = new AtomicInteger();
|
|
|
|
public ConcurrentListenerAdders() {
|
|
promise = factory().unresolved();
|
|
}
|
|
|
|
@Actor
|
|
public void adder1() {
|
|
promise.addDirectListener(v -> callCount.incrementAndGet());
|
|
}
|
|
|
|
@Actor
|
|
public void adder2() {
|
|
promise.addDirectListener(v -> callCount.incrementAndGet());
|
|
}
|
|
|
|
@Arbiter
|
|
public void arbiter(I_Result r) {
|
|
promise.complete(42);
|
|
r.r1 = callCount.get();
|
|
}
|
|
|
|
}
|
|
|
|
@JCStressTest
|
|
@Outcome(id = "42, 1", expect = Expect.ACCEPTABLE, desc = "Write visible")
|
|
@Outcome(id = "null, 0", expect = Expect.ACCEPTABLE, desc = "Neither visible yet")
|
|
@Outcome(id = "42, 0", expect = Expect.ACCEPTABLE, desc = "Element visible but size not yet")
|
|
@Outcome(id = "null, 1", expect = Expect.FORBIDDEN, desc = "Size visible but element not")
|
|
@State
|
|
public static class ArrayWriteRead {
|
|
|
|
final ConcurrentResultArray<Integer> array = new ConcurrentResultArray<>(4);
|
|
|
|
@Actor
|
|
public void writer() {
|
|
array.set(0, 42);
|
|
}
|
|
|
|
@Actor
|
|
public void reader(L_Result r) {
|
|
int size = array.toList().size();
|
|
Integer elem = size > 0 ? array.toList().get(0) : null;
|
|
r.r1 = elem + ", " + size;
|
|
}
|
|
|
|
}
|
|
|
|
}
|