diff --git a/vertx-core/src/main/java/io/vertx/core/impl/VertxImpl.java b/vertx-core/src/main/java/io/vertx/core/impl/VertxImpl.java index 9fdd27fbb6e..22c8ef71a87 100644 --- a/vertx-core/src/main/java/io/vertx/core/impl/VertxImpl.java +++ b/vertx-core/src/main/java/io/vertx/core/impl/VertxImpl.java @@ -80,7 +80,6 @@ import java.nio.charset.StandardCharsets; import java.util.*; import java.util.concurrent.*; -import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicLong; import java.util.function.Function; @@ -107,6 +106,16 @@ public class VertxImpl implements VertxInternal, MetricsProvider { // https://github.com/eclipse-vertx/vert.x/issues/4611 private static final Logger log = LoggerFactory.getLogger(VertxImpl.class); + private static final VarHandle INTERNAL_TIMER_HANDLER_DISPOSED; + + static { + try { + INTERNAL_TIMER_HANDLER_DISPOSED = MethodHandles.lookup() + .findVarHandle(InternalTimerHandler.class, "disposed", boolean.class); + } catch (NoSuchFieldException | IllegalAccessException e) { + throw new IllegalArgumentException(e); + } + } static final Object[] EMPTY_CONTEXT_LOCALS = new Object[0]; private static final String CLUSTER_MAP_NAME = "__vertx.haInfo"; @@ -114,6 +123,10 @@ public class VertxImpl implements VertxInternal, MetricsProvider { private static final int NETTY_IO_RATIO = Integer.getInteger(NETTY_IO_RATIO_PROPERTY_NAME, 50); private static final VarHandle LOCALS_UPDATER = MethodHandles.arrayElementVarHandle(EventLoop[].class); + private static boolean disposedCAS(InternalTimerHandler handler) { + return INTERNAL_TIMER_HANDLER_DISPOSED.compareAndSet(handler, false, true); + } + // Not cached for graalvm private static ThreadFactory virtualThreadFactory() { try { @@ -1044,7 +1057,7 @@ class InternalTimerHandler implements Handler, Closeable, Runnable { private final boolean periodic; private final long id; private final ContextInternal context; - private final AtomicBoolean disposed = new AtomicBoolean(); + private volatile boolean disposed; private volatile java.util.concurrent.Future future; InternalTimerHandler(long id, Handler runnable, boolean periodic, ContextInternal context) { @@ -1065,10 +1078,10 @@ public void run() { public void handle(Void v) { if (periodic) { - if (!disposed.get()) { + if (!disposed) { handler.handle(id); } - } else if (disposed.compareAndSet(false, true)) { + } else if (disposedCAS(this)) { timeouts.remove(id); try { handler.handle(id); @@ -1090,7 +1103,7 @@ private boolean cancel() { } private boolean tryCancel() { - if (disposed.compareAndSet(false, true)) { + if (disposedCAS(this)) { timeouts.remove(id); future.cancel(false); return true;