diff --git a/src/main/java/org/xbib/event/ScheduledFutureTask.java b/src/main/java/org/xbib/event/ScheduledFutureTask.java index 5dbc178..596cee7 100644 --- a/src/main/java/org/xbib/event/ScheduledFutureTask.java +++ b/src/main/java/org/xbib/event/ScheduledFutureTask.java @@ -37,32 +37,34 @@ public final class ScheduledFutureTask extends PromiseTask implements Sche private int queueIndex = INDEX_NOT_IN_QUEUE; public ScheduledFutureTask(AbstractScheduledEventExecutor executor, - Runnable runnable, long nanoTime) { - + Runnable runnable, + long nanoTime) { super(executor, runnable); deadlineNanos = nanoTime; periodNanos = 0; } public ScheduledFutureTask(AbstractScheduledEventExecutor executor, - Runnable runnable, long nanoTime, long period) { - + Runnable runnable, + long nanoTime, + long period) { super(executor, runnable); deadlineNanos = nanoTime; periodNanos = validatePeriod(period); } public ScheduledFutureTask(AbstractScheduledEventExecutor executor, - Callable callable, long nanoTime, long period) { - + Callable callable, + long nanoTime, + long period) { super(executor, callable); deadlineNanos = nanoTime; periodNanos = validatePeriod(period); } public ScheduledFutureTask(AbstractScheduledEventExecutor executor, - Callable callable, long nanoTime) { - + Callable callable, + long nanoTime) { super(executor, callable); deadlineNanos = nanoTime; periodNanos = 0; @@ -203,7 +205,6 @@ public final class ScheduledFutureTask extends PromiseTask implements Sche protected StringBuilder toStringBuilder() { StringBuilder buf = super.toStringBuilder(); buf.setCharAt(buf.length() - 1, ','); - return buf.append(" deadline: ") .append(deadlineNanos) .append(", period: ") diff --git a/src/main/java/org/xbib/event/loop/EventLoop.java b/src/main/java/org/xbib/event/loop/EventLoop.java index 0392809..7592928 100644 --- a/src/main/java/org/xbib/event/loop/EventLoop.java +++ b/src/main/java/org/xbib/event/loop/EventLoop.java @@ -1,4 +1,3 @@ - package org.xbib.event.loop; public interface EventLoop extends OrderedEventExecutor, EventLoopGroup { diff --git a/src/main/java/org/xbib/event/loop/SingleThreadEventExecutor.java b/src/main/java/org/xbib/event/loop/SingleThreadEventExecutor.java index 11fdc12..2c9efaa 100644 --- a/src/main/java/org/xbib/event/loop/SingleThreadEventExecutor.java +++ b/src/main/java/org/xbib/event/loop/SingleThreadEventExecutor.java @@ -38,8 +38,8 @@ import java.util.logging.Logger; */ public abstract class SingleThreadEventExecutor extends AbstractScheduledEventExecutor implements OrderedEventExecutor { - static final int DEFAULT_MAX_PENDING_EXECUTOR_TASKS = Math.max(16, - Integer.getInteger("org.xbib.eventexecutor.maxPendingTasks", Integer.MAX_VALUE)); + static final int DEFAULT_MAX_PENDING_EXECUTOR_TASKS = + Math.max(16, Integer.getInteger("org.xbib.eventexecutor.maxPendingTasks", Integer.MAX_VALUE)); private static final Logger logger = Logger.getLogger(SingleThreadEventExecutor.class.getName()); @@ -49,11 +49,8 @@ public abstract class SingleThreadEventExecutor extends AbstractScheduledEventEx private static final int ST_SHUTDOWN = 4; private static final int ST_TERMINATED = 5; - private static final Runnable NOOP_TASK = new Runnable() { - @Override - public void run() { - // Do nothing. - } + private static final Runnable NOOP_TASK = () -> { + // Do nothing. }; private static final AtomicIntegerFieldUpdater STATE_UPDATER = @@ -71,7 +68,7 @@ public abstract class SingleThreadEventExecutor extends AbstractScheduledEventEx private volatile boolean interrupted; private final CountDownLatch threadLock = new CountDownLatch(1); - private final Set shutdownHooks = new LinkedHashSet(); + private final Set shutdownHooks = new LinkedHashSet<>(); private final boolean addTaskWakesUp; private final int maxPendingTasks; private final RejectedExecutionHandler rejectedExecutionHandler; @@ -95,8 +92,9 @@ public abstract class SingleThreadEventExecutor extends AbstractScheduledEventEx * @param addTaskWakesUp {@code true} if and only if invocation of {@link #addTask(Runnable)} will wake up the * executor thread */ - protected SingleThreadEventExecutor( - EventExecutorGroup parent, ThreadFactory threadFactory, boolean addTaskWakesUp) { + protected SingleThreadEventExecutor(EventExecutorGroup parent, + ThreadFactory threadFactory, + boolean addTaskWakesUp) { this(parent, new ThreadPerTaskExecutor(threadFactory), addTaskWakesUp); } @@ -110,9 +108,11 @@ public abstract class SingleThreadEventExecutor extends AbstractScheduledEventEx * @param maxPendingTasks the maximum number of pending tasks before new tasks will be rejected. * @param rejectedHandler the {@link RejectedExecutionHandler} to use. */ - protected SingleThreadEventExecutor( - EventExecutorGroup parent, ThreadFactory threadFactory, - boolean addTaskWakesUp, int maxPendingTasks, RejectedExecutionHandler rejectedHandler) { + protected SingleThreadEventExecutor(EventExecutorGroup parent, + ThreadFactory threadFactory, + boolean addTaskWakesUp, + int maxPendingTasks, + RejectedExecutionHandler rejectedHandler) { this(parent, new ThreadPerTaskExecutor(threadFactory), addTaskWakesUp, maxPendingTasks, rejectedHandler); } @@ -124,7 +124,9 @@ public abstract class SingleThreadEventExecutor extends AbstractScheduledEventEx * @param addTaskWakesUp {@code true} if and only if invocation of {@link #addTask(Runnable)} will wake up the * executor thread */ - protected SingleThreadEventExecutor(EventExecutorGroup parent, Executor executor, boolean addTaskWakesUp) { + protected SingleThreadEventExecutor(EventExecutorGroup parent, + Executor executor, + boolean addTaskWakesUp) { this(parent, executor, addTaskWakesUp, DEFAULT_MAX_PENDING_EXECUTOR_TASKS, RejectedExecutionHandlers.reject()); } @@ -138,8 +140,10 @@ public abstract class SingleThreadEventExecutor extends AbstractScheduledEventEx * @param maxPendingTasks the maximum number of pending tasks before new tasks will be rejected. * @param rejectedHandler the {@link RejectedExecutionHandler} to use. */ - protected SingleThreadEventExecutor(EventExecutorGroup parent, Executor executor, - boolean addTaskWakesUp, int maxPendingTasks, + protected SingleThreadEventExecutor(EventExecutorGroup parent, + Executor executor, + boolean addTaskWakesUp, + int maxPendingTasks, RejectedExecutionHandler rejectedHandler) { super(parent); this.addTaskWakesUp = addTaskWakesUp; @@ -149,8 +153,10 @@ public abstract class SingleThreadEventExecutor extends AbstractScheduledEventEx rejectedExecutionHandler = Objects.requireNonNull(rejectedHandler, "rejectedHandler"); } - protected SingleThreadEventExecutor(EventExecutorGroup parent, Executor executor, - boolean addTaskWakesUp, Queue taskQueue, + protected SingleThreadEventExecutor(EventExecutorGroup parent, + Executor executor, + boolean addTaskWakesUp, + Queue taskQueue, RejectedExecutionHandler rejectedHandler) { super(parent); this.addTaskWakesUp = addTaskWakesUp; diff --git a/src/main/java/org/xbib/event/loop/nio/NioEventLoop.java b/src/main/java/org/xbib/event/loop/nio/NioEventLoop.java index 0e03c00..e40792c 100644 --- a/src/main/java/org/xbib/event/loop/nio/NioEventLoop.java +++ b/src/main/java/org/xbib/event/loop/nio/NioEventLoop.java @@ -8,12 +8,15 @@ import org.xbib.event.loop.SingleThreadEventLoop; import org.xbib.event.util.IntSupplier; import java.io.IOException; +import java.lang.reflect.Field; import java.nio.channels.CancelledKeyException; import java.nio.channels.SelectableChannel; import java.nio.channels.Selector; import java.nio.channels.SelectionKey; import java.nio.channels.spi.SelectorProvider; +import java.security.AccessController; +import java.security.PrivilegedAction; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; @@ -104,7 +107,7 @@ public final class NioEventLoop extends SingleThreadEventLoop { rejectedExecutionHandler); this.provider = Objects.requireNonNull(selectorProvider, "selectorProvider"); this.selectStrategy = Objects.requireNonNull(strategy, "selectStrategy"); - final SelectorTuple selectorTuple = null; // openSelector(); + final SelectorTuple selectorTuple = openSelector(); this.selector = selectorTuple.selector; this.unwrappedSelector = selectorTuple.unwrappedSelector; } @@ -131,100 +134,83 @@ public final class NioEventLoop extends SingleThreadEventLoop { } } - /*private SelectorTuple openSelector() { + private SelectorTuple openSelector() { final Selector unwrappedSelector; try { unwrappedSelector = provider.openSelector(); } catch (IOException e) { - throw new ChannelException("failed to open a new selector", e); + throw new EventLoopException("failed to open a new selector", e); } if (DISABLE_KEY_SET_OPTIMIZATION) { return new SelectorTuple(unwrappedSelector); } - Object maybeSelectorImplClass = AccessController.doPrivileged(new PrivilegedAction() { - @Override - public Object run() { - try { - return Class.forName( - "sun.nio.ch.SelectorImpl", - false, - PlatformDependent.getSystemClassLoader()); - } catch (Throwable cause) { - return cause; - } - } - }); + Class maybeSelectorImplClass = null; + try { + maybeSelectorImplClass = Class.forName("sun.nio.ch.SelectorImpl", false, + ClassLoader.getSystemClassLoader()); + } catch (ClassNotFoundException e) { + // + } - if (!(maybeSelectorImplClass instanceof Class) || - // ensure the current selector implementation is what we can instrument. - !((Class) maybeSelectorImplClass).isAssignableFrom(unwrappedSelector.getClass())) { - if (maybeSelectorImplClass instanceof Throwable) { - Throwable t = (Throwable) maybeSelectorImplClass; - logger.log(Level.FINEST, "failed to instrument a special java.util.Set into: " + unwrappedSelector, t); - } + // ensure the current selector implementation is what we can instrument. + if (maybeSelectorImplClass == null || + !maybeSelectorImplClass.isAssignableFrom(unwrappedSelector.getClass())) { return new SelectorTuple(unwrappedSelector); } - final Class selectorImplClass = (Class) maybeSelectorImplClass; + final Class selectorImplClass = maybeSelectorImplClass; final SelectedSelectionKeySet selectedKeySet = new SelectedSelectionKeySet(); - Object maybeException = AccessController.doPrivileged(new PrivilegedAction() { - @Override - public Object run() { - try { - Field selectedKeysField = selectorImplClass.getDeclaredField("selectedKeys"); - Field publicSelectedKeysField = selectorImplClass.getDeclaredField("publicSelectedKeys"); + Object maybeException = null; + try { + Field selectedKeysField = selectorImplClass.getDeclaredField("selectedKeys"); + Field publicSelectedKeysField = selectorImplClass.getDeclaredField("publicSelectedKeys"); - if (PlatformDependent.javaVersion() >= 9 && PlatformDependent.hasUnsafe()) { - // Let us try to use sun.misc.Unsafe to replace the SelectionKeySet. - // This allows us to also do this in Java9+ without any extra flags. - long selectedKeysFieldOffset = PlatformDependent.objectFieldOffset(selectedKeysField); - long publicSelectedKeysFieldOffset = - PlatformDependent.objectFieldOffset(publicSelectedKeysField); + if (PlatformDependent.javaVersion() >= 9 && PlatformDependent.hasUnsafe()) { + // Let us try to use sun.misc.Unsafe to replace the SelectionKeySet. + // This allows us to also do this in Java9+ without any extra flags. + long selectedKeysFieldOffset = PlatformDependent.objectFieldOffset(selectedKeysField); + long publicSelectedKeysFieldOffset = + PlatformDependent.objectFieldOffset(publicSelectedKeysField); - if (selectedKeysFieldOffset != -1 && publicSelectedKeysFieldOffset != -1) { - PlatformDependent.putObject( - unwrappedSelector, selectedKeysFieldOffset, selectedKeySet); - PlatformDependent.putObject( - unwrappedSelector, publicSelectedKeysFieldOffset, selectedKeySet); - return null; - } - // We could not retrieve the offset, lets try reflection as last-resort. - } - - Throwable cause = ReflectionUtil.trySetAccessible(selectedKeysField, true); - if (cause != null) { - return cause; - } - cause = ReflectionUtil.trySetAccessible(publicSelectedKeysField, true); - if (cause != null) { - return cause; - } - - selectedKeysField.set(unwrappedSelector, selectedKeySet); - publicSelectedKeysField.set(unwrappedSelector, selectedKeySet); + if (selectedKeysFieldOffset != -1 && publicSelectedKeysFieldOffset != -1) { + PlatformDependent.putObject( + unwrappedSelector, selectedKeysFieldOffset, selectedKeySet); + PlatformDependent.putObject( + unwrappedSelector, publicSelectedKeysFieldOffset, selectedKeySet); return null; - } catch (NoSuchFieldException e) { - return e; - } catch (IllegalAccessException e) { - return e; } + // We could not retrieve the offset, lets try reflection as last-resort. } - }); + + Throwable cause = ReflectionUtil.trySetAccessible(selectedKeysField, true); + if (cause != null) { + return cause; + } + cause = ReflectionUtil.trySetAccessible(publicSelectedKeysField, true); + if (cause != null) { + return cause; + } + + selectedKeysField.set(unwrappedSelector, selectedKeySet); + publicSelectedKeysField.set(unwrappedSelector, selectedKeySet); + return null; + } catch (NoSuchFieldException | IllegalAccessException e) { + maybeException = e; + } if (maybeException instanceof Exception) { selectedKeys = null; Exception e = (Exception) maybeException; - logger.trace("failed to instrument a special java.util.Set into: {}", unwrappedSelector, e); + logger.log(Level.FINEST, "failed to instrument a special java.util.Set into: " + unwrappedSelector, e); return new SelectorTuple(unwrappedSelector); } selectedKeys = selectedKeySet; - logger.trace("instrumented a special java.util.Set into: {}", unwrappedSelector); - return new SelectorTuple(unwrappedSelector, - new SelectedSelectionKeySetSelector(unwrappedSelector, selectedKeySet)); - }*/ + logger.log(Level.FINEST, "instrumented a special java.util.Set into: " + unwrappedSelector); + return new SelectorTuple(unwrappedSelector, new SelectedSelectionKeySetSelector(unwrappedSelector, selectedKeySet)); + } /** * Returns the {@link SelectorProvider} used by this {@link NioEventLoop} to obtain the {@link Selector}. diff --git a/src/main/java/org/xbib/event/loop/nio/SelectedSelectionKeySetSelector.java b/src/main/java/org/xbib/event/loop/nio/SelectedSelectionKeySetSelector.java new file mode 100644 index 0000000..e6bc548 --- /dev/null +++ b/src/main/java/org/xbib/event/loop/nio/SelectedSelectionKeySetSelector.java @@ -0,0 +1,65 @@ +package org.xbib.event.loop.nio; + +import java.io.IOException; +import java.nio.channels.SelectionKey; +import java.nio.channels.Selector; +import java.nio.channels.spi.SelectorProvider; +import java.util.Set; + +final class SelectedSelectionKeySetSelector extends Selector { + private final SelectedSelectionKeySet selectionKeys; + private final Selector delegate; + + SelectedSelectionKeySetSelector(Selector delegate, SelectedSelectionKeySet selectionKeys) { + this.delegate = delegate; + this.selectionKeys = selectionKeys; + } + + @Override + public boolean isOpen() { + return delegate.isOpen(); + } + + @Override + public SelectorProvider provider() { + return delegate.provider(); + } + + @Override + public Set keys() { + return delegate.keys(); + } + + @Override + public Set selectedKeys() { + return delegate.selectedKeys(); + } + + @Override + public int selectNow() throws IOException { + selectionKeys.reset(); + return delegate.selectNow(); + } + + @Override + public int select(long timeout) throws IOException { + selectionKeys.reset(); + return delegate.select(timeout); + } + + @Override + public int select() throws IOException { + selectionKeys.reset(); + return delegate.select(); + } + + @Override + public Selector wakeup() { + return delegate.wakeup(); + } + + @Override + public void close() throws IOException { + delegate.close(); + } +}