Java 8 migration: replace anonymous types with lambda (#8751)
Motivation: We can use lambdas instead of anonymous inner class to improve readablity Modification: Replace anonymous inner class with lambda Result: Cleaner code that uses Java8 features
This commit is contained in:
parent
7b6336f1fd
commit
d08ecccd9a
@ -244,17 +244,14 @@ public abstract class AbstractBootstrap<B extends AbstractBootstrap<B, C, F>, C
|
|||||||
} else {
|
} else {
|
||||||
// Registration future is almost always fulfilled already, but just in case it's not.
|
// Registration future is almost always fulfilled already, but just in case it's not.
|
||||||
final ChannelPromise promise = channel.newPromise();
|
final ChannelPromise promise = channel.newPromise();
|
||||||
regFuture.addListener(new ChannelFutureListener() {
|
regFuture.addListener((ChannelFutureListener) future -> {
|
||||||
@Override
|
Throwable cause = future.cause();
|
||||||
public void operationComplete(ChannelFuture future) throws Exception {
|
if (cause != null) {
|
||||||
Throwable cause = future.cause();
|
// Registration on the EventLoop failed so fail the ChannelPromise directly to not cause an
|
||||||
if (cause != null) {
|
// IllegalStateException once we try to access the EventLoop of the Channel.
|
||||||
// Registration on the EventLoop failed so fail the ChannelPromise directly to not cause an
|
promise.setFailure(cause);
|
||||||
// IllegalStateException once we try to access the EventLoop of the Channel.
|
} else {
|
||||||
promise.setFailure(cause);
|
doBind0(regFuture, channel, localAddress, promise);
|
||||||
} else {
|
|
||||||
doBind0(regFuture, channel, localAddress, promise);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return promise;
|
return promise;
|
||||||
@ -271,22 +268,14 @@ public abstract class AbstractBootstrap<B extends AbstractBootstrap<B, C, F>, C
|
|||||||
}
|
}
|
||||||
|
|
||||||
final ChannelPromise promise = channel.newPromise();
|
final ChannelPromise promise = channel.newPromise();
|
||||||
loop.execute(new Runnable() {
|
loop.execute(() -> init(channel).addListener((ChannelFutureListener) future -> {
|
||||||
@Override
|
if (future.isSuccess()) {
|
||||||
public void run() {
|
channel.register(promise);
|
||||||
init(channel).addListener(new ChannelFutureListener() {
|
} else {
|
||||||
@Override
|
channel.unsafe().closeForcibly();
|
||||||
public void operationComplete(ChannelFuture future) throws Exception {
|
promise.setFailure(future.cause());
|
||||||
if (future.isSuccess()) {
|
|
||||||
channel.register(promise);
|
|
||||||
} else {
|
|
||||||
channel.unsafe().closeForcibly();
|
|
||||||
promise.setFailure(future.cause());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
});
|
}));
|
||||||
|
|
||||||
return promise;
|
return promise;
|
||||||
}
|
}
|
||||||
@ -301,14 +290,11 @@ public abstract class AbstractBootstrap<B extends AbstractBootstrap<B, C, F>, C
|
|||||||
|
|
||||||
// This method is invoked before channelRegistered() is triggered. Give user handlers a chance to set up
|
// This method is invoked before channelRegistered() is triggered. Give user handlers a chance to set up
|
||||||
// the pipeline in its channelRegistered() implementation.
|
// the pipeline in its channelRegistered() implementation.
|
||||||
channel.eventLoop().execute(new Runnable() {
|
channel.eventLoop().execute(() -> {
|
||||||
@Override
|
if (regFuture.isSuccess()) {
|
||||||
public void run() {
|
channel.bind(localAddress, promise).addListener(ChannelFutureListener.CLOSE_ON_FAILURE);
|
||||||
if (regFuture.isSuccess()) {
|
} else {
|
||||||
channel.bind(localAddress, promise).addListener(ChannelFutureListener.CLOSE_ON_FAILURE);
|
promise.setFailure(regFuture.cause());
|
||||||
} else {
|
|
||||||
promise.setFailure(regFuture.cause());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -206,19 +206,16 @@ public class Bootstrap extends AbstractBootstrap<Bootstrap, Channel, ChannelFact
|
|||||||
} else {
|
} else {
|
||||||
// Registration future is almost always fulfilled already, but just in case it's not.
|
// Registration future is almost always fulfilled already, but just in case it's not.
|
||||||
final ChannelPromise promise = channel.newPromise();
|
final ChannelPromise promise = channel.newPromise();
|
||||||
regFuture.addListener(new ChannelFutureListener() {
|
regFuture.addListener((ChannelFutureListener) future -> {
|
||||||
@Override
|
// Directly obtain the cause and do a null check so we only need one volatile read in case of a
|
||||||
public void operationComplete(ChannelFuture future) throws Exception {
|
// failure.
|
||||||
// Directly obtain the cause and do a null check so we only need one volatile read in case of a
|
Throwable cause = future.cause();
|
||||||
// failure.
|
if (cause != null) {
|
||||||
Throwable cause = future.cause();
|
// Registration on the EventLoop failed so fail the ChannelPromise directly to not cause an
|
||||||
if (cause != null) {
|
// IllegalStateException once we try to access the EventLoop of the Channel.
|
||||||
// Registration on the EventLoop failed so fail the ChannelPromise directly to not cause an
|
promise.setFailure(cause);
|
||||||
// IllegalStateException once we try to access the EventLoop of the Channel.
|
} else {
|
||||||
promise.setFailure(cause);
|
doResolveAndConnect0(channel, remoteAddress, localAddress, promise);
|
||||||
} else {
|
|
||||||
doResolveAndConnect0(channel, remoteAddress, localAddress, promise);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return promise;
|
return promise;
|
||||||
@ -254,15 +251,12 @@ public class Bootstrap extends AbstractBootstrap<Bootstrap, Channel, ChannelFact
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Wait until the name resolution is finished.
|
// Wait until the name resolution is finished.
|
||||||
resolveFuture.addListener(new FutureListener<SocketAddress>() {
|
resolveFuture.addListener((FutureListener<SocketAddress>) future -> {
|
||||||
@Override
|
if (future.cause() != null) {
|
||||||
public void operationComplete(Future<SocketAddress> future) throws Exception {
|
channel.close();
|
||||||
if (future.cause() != null) {
|
promise.setFailure(future.cause());
|
||||||
channel.close();
|
} else {
|
||||||
promise.setFailure(future.cause());
|
doConnect(future.getNow(), localAddress, promise);
|
||||||
} else {
|
|
||||||
doConnect(future.getNow(), localAddress, promise);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} catch (Throwable cause) {
|
} catch (Throwable cause) {
|
||||||
@ -277,16 +271,13 @@ public class Bootstrap extends AbstractBootstrap<Bootstrap, Channel, ChannelFact
|
|||||||
// This method is invoked before channelRegistered() is triggered. Give user handlers a chance to set up
|
// This method is invoked before channelRegistered() is triggered. Give user handlers a chance to set up
|
||||||
// the pipeline in its channelRegistered() implementation.
|
// the pipeline in its channelRegistered() implementation.
|
||||||
final Channel channel = connectPromise.channel();
|
final Channel channel = connectPromise.channel();
|
||||||
channel.eventLoop().execute(new Runnable() {
|
channel.eventLoop().execute(() -> {
|
||||||
@Override
|
if (localAddress == null) {
|
||||||
public void run() {
|
channel.connect(remoteAddress, connectPromise);
|
||||||
if (localAddress == null) {
|
} else {
|
||||||
channel.connect(remoteAddress, connectPromise);
|
channel.connect(remoteAddress, localAddress, connectPromise);
|
||||||
} else {
|
|
||||||
channel.connect(remoteAddress, localAddress, connectPromise);
|
|
||||||
}
|
|
||||||
connectPromise.addListener(ChannelFutureListener.CLOSE_ON_FAILURE);
|
|
||||||
}
|
}
|
||||||
|
connectPromise.addListener(ChannelFutureListener.CLOSE_ON_FAILURE);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -214,13 +214,10 @@ public class ServerBootstrap extends AbstractBootstrap<ServerBootstrap, ServerCh
|
|||||||
pipeline.addLast(handler);
|
pipeline.addLast(handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
ch.eventLoop().execute(new Runnable() {
|
ch.eventLoop().execute(() -> {
|
||||||
@Override
|
pipeline.addLast(new ServerBootstrapAcceptor(
|
||||||
public void run() {
|
ch, currentChildHandler, currentChildOptions, currentChildAttrs));
|
||||||
pipeline.addLast(new ServerBootstrapAcceptor(
|
promise.setSuccess();
|
||||||
ch, currentChildHandler, currentChildOptions, currentChildAttrs));
|
|
||||||
promise.setSuccess();
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -277,12 +274,7 @@ public class ServerBootstrap extends AbstractBootstrap<ServerBootstrap, ServerCh
|
|||||||
// not be able to load the class because of the file limit it already reached.
|
// not be able to load the class because of the file limit it already reached.
|
||||||
//
|
//
|
||||||
// See https://github.com/netty/netty/issues/1328
|
// See https://github.com/netty/netty/issues/1328
|
||||||
enableAutoReadTask = new Runnable() {
|
enableAutoReadTask = () -> channel.config().setAutoRead(true);
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
channel.config().setAutoRead(true);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -295,12 +287,7 @@ public class ServerBootstrap extends AbstractBootstrap<ServerBootstrap, ServerCh
|
|||||||
initChild(child);
|
initChild(child);
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
childEventLoop.execute(new Runnable() {
|
childEventLoop.execute(() -> initChild(child));
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
initChild(child);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} catch (Throwable cause) {
|
} catch (Throwable cause) {
|
||||||
forceClose(child, cause);
|
forceClose(child, cause);
|
||||||
}
|
}
|
||||||
@ -319,12 +306,9 @@ public class ServerBootstrap extends AbstractBootstrap<ServerBootstrap, ServerCh
|
|||||||
child.attr((AttributeKey<Object>) e.getKey()).set(e.getValue());
|
child.attr((AttributeKey<Object>) e.getKey()).set(e.getValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
child.register().addListener(new ChannelFutureListener() {
|
child.register().addListener((ChannelFutureListener) future -> {
|
||||||
@Override
|
if (!future.isSuccess()) {
|
||||||
public void operationComplete(ChannelFuture future) throws Exception {
|
forceClose(child, future.cause());
|
||||||
if (!future.isSuccess()) {
|
|
||||||
forceClose(child, future.cause());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
|
@ -550,12 +550,9 @@ public abstract class AbstractChannel extends DefaultAttributeMap implements Cha
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!wasActive && isActive()) {
|
if (!wasActive && isActive()) {
|
||||||
invokeLater(new Runnable() {
|
invokeLater(() -> {
|
||||||
@Override
|
pipeline.fireChannelActive();
|
||||||
public void run() {
|
readIfIsAutoRead();
|
||||||
pipeline.fireChannelActive();
|
|
||||||
readIfIsAutoRead();
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -580,12 +577,7 @@ public abstract class AbstractChannel extends DefaultAttributeMap implements Cha
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (wasActive && !isActive()) {
|
if (wasActive && !isActive()) {
|
||||||
invokeLater(new Runnable() {
|
invokeLater(pipeline::fireChannelInactive);
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
pipeline.fireChannelInactive();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
safeSetSuccess(promise);
|
safeSetSuccess(promise);
|
||||||
@ -631,24 +623,17 @@ public abstract class AbstractChannel extends DefaultAttributeMap implements Cha
|
|||||||
new ChannelOutputShutdownException("Channel output shutdown", cause);
|
new ChannelOutputShutdownException("Channel output shutdown", cause);
|
||||||
Executor closeExecutor = prepareToClose();
|
Executor closeExecutor = prepareToClose();
|
||||||
if (closeExecutor != null) {
|
if (closeExecutor != null) {
|
||||||
closeExecutor.execute(new Runnable() {
|
closeExecutor.execute(() -> {
|
||||||
@Override
|
try {
|
||||||
public void run() {
|
// Execute the shutdown.
|
||||||
try {
|
doShutdownOutput();
|
||||||
// Execute the shutdown.
|
promise.setSuccess();
|
||||||
doShutdownOutput();
|
} catch (Throwable err) {
|
||||||
promise.setSuccess();
|
promise.setFailure(err);
|
||||||
} catch (Throwable err) {
|
} finally {
|
||||||
promise.setFailure(err);
|
// Dispatch to the EventLoop
|
||||||
} finally {
|
eventLoop().execute(() ->
|
||||||
// Dispatch to the EventLoop
|
closeOutboundBufferForShutdown(pipeline, outboundBuffer, shutdownCause));
|
||||||
eventLoop().execute(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
closeOutboundBufferForShutdown(pipeline, outboundBuffer, shutdownCause);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
@ -683,12 +668,7 @@ public abstract class AbstractChannel extends DefaultAttributeMap implements Cha
|
|||||||
safeSetSuccess(promise);
|
safeSetSuccess(promise);
|
||||||
} else if (!(promise instanceof VoidChannelPromise)) { // Only needed if no VoidChannelPromise.
|
} else if (!(promise instanceof VoidChannelPromise)) { // Only needed if no VoidChannelPromise.
|
||||||
// This means close() was called before so we just register a listener and return
|
// This means close() was called before so we just register a listener and return
|
||||||
closeFuture.addListener(new ChannelFutureListener() {
|
closeFuture.addListener((ChannelFutureListener) future -> promise.setSuccess());
|
||||||
@Override
|
|
||||||
public void operationComplete(ChannelFuture future) throws Exception {
|
|
||||||
promise.setSuccess();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -700,26 +680,20 @@ public abstract class AbstractChannel extends DefaultAttributeMap implements Cha
|
|||||||
this.outboundBuffer = null; // Disallow adding any messages and flushes to outboundBuffer.
|
this.outboundBuffer = null; // Disallow adding any messages and flushes to outboundBuffer.
|
||||||
Executor closeExecutor = prepareToClose();
|
Executor closeExecutor = prepareToClose();
|
||||||
if (closeExecutor != null) {
|
if (closeExecutor != null) {
|
||||||
closeExecutor.execute(new Runnable() {
|
closeExecutor.execute(() -> {
|
||||||
@Override
|
try {
|
||||||
public void run() {
|
// Execute the close.
|
||||||
try {
|
doClose0(promise);
|
||||||
// Execute the close.
|
} finally {
|
||||||
doClose0(promise);
|
// Call invokeLater so closeAndDeregister is executed in the EventLoop again!
|
||||||
} finally {
|
invokeLater(() -> {
|
||||||
// Call invokeLater so closeAndDeregister is executed in the EventLoop again!
|
if (outboundBuffer != null) {
|
||||||
invokeLater(new Runnable() {
|
// Fail all the queued messages
|
||||||
@Override
|
outboundBuffer.failFlushed(cause, notify);
|
||||||
public void run() {
|
outboundBuffer.close(closeCause);
|
||||||
if (outboundBuffer != null) {
|
}
|
||||||
// Fail all the queued messages
|
fireChannelInactiveAndDeregister(wasActive);
|
||||||
outboundBuffer.failFlushed(cause, notify);
|
});
|
||||||
outboundBuffer.close(closeCause);
|
|
||||||
}
|
|
||||||
fireChannelInactiveAndDeregister(wasActive);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
@ -734,12 +708,7 @@ public abstract class AbstractChannel extends DefaultAttributeMap implements Cha
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (inFlush0) {
|
if (inFlush0) {
|
||||||
invokeLater(new Runnable() {
|
invokeLater(() -> fireChannelInactiveAndDeregister(wasActive));
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
fireChannelInactiveAndDeregister(wasActive);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
} else {
|
||||||
fireChannelInactiveAndDeregister(wasActive);
|
fireChannelInactiveAndDeregister(wasActive);
|
||||||
}
|
}
|
||||||
@ -796,27 +765,24 @@ public abstract class AbstractChannel extends DefaultAttributeMap implements Cha
|
|||||||
//
|
//
|
||||||
// See:
|
// See:
|
||||||
// https://github.com/netty/netty/issues/4435
|
// https://github.com/netty/netty/issues/4435
|
||||||
invokeLater(new Runnable() {
|
invokeLater(() -> {
|
||||||
@Override
|
try {
|
||||||
public void run() {
|
doDeregister();
|
||||||
try {
|
} catch (Throwable t) {
|
||||||
doDeregister();
|
logger.warn("Unexpected exception occurred while deregistering a channel.", t);
|
||||||
} catch (Throwable t) {
|
} finally {
|
||||||
logger.warn("Unexpected exception occurred while deregistering a channel.", t);
|
if (fireChannelInactive) {
|
||||||
} finally {
|
pipeline.fireChannelInactive();
|
||||||
if (fireChannelInactive) {
|
|
||||||
pipeline.fireChannelInactive();
|
|
||||||
}
|
|
||||||
// Some transports like local and AIO does not allow the deregistration of
|
|
||||||
// an open channel. Their doDeregister() calls close(). Consequently,
|
|
||||||
// close() calls deregister() again - no need to fire channelUnregistered, so check
|
|
||||||
// if it was registered.
|
|
||||||
if (registered) {
|
|
||||||
registered = false;
|
|
||||||
pipeline.fireChannelUnregistered();
|
|
||||||
}
|
|
||||||
safeSetSuccess(promise);
|
|
||||||
}
|
}
|
||||||
|
// Some transports like local and AIO does not allow the deregistration of
|
||||||
|
// an open channel. Their doDeregister() calls close(). Consequently,
|
||||||
|
// close() calls deregister() again - no need to fire channelUnregistered, so check
|
||||||
|
// if it was registered.
|
||||||
|
if (registered) {
|
||||||
|
registered = false;
|
||||||
|
pipeline.fireChannelUnregistered();
|
||||||
|
}
|
||||||
|
safeSetSuccess(promise);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -832,12 +798,7 @@ public abstract class AbstractChannel extends DefaultAttributeMap implements Cha
|
|||||||
try {
|
try {
|
||||||
doBeginRead();
|
doBeginRead();
|
||||||
} catch (final Exception e) {
|
} catch (final Exception e) {
|
||||||
invokeLater(new Runnable() {
|
invokeLater(() -> pipeline.fireExceptionCaught(e));
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
pipeline.fireExceptionCaught(e);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
close(voidPromise());
|
close(voidPromise());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -232,12 +232,8 @@ abstract class AbstractChannelHandlerContext extends DefaultAttributeMap
|
|||||||
private static boolean isSkippable(
|
private static boolean isSkippable(
|
||||||
final Class<?> handlerType, final String methodName, final Class<?>... paramTypes) throws Exception {
|
final Class<?> handlerType, final String methodName, final Class<?>... paramTypes) throws Exception {
|
||||||
|
|
||||||
return AccessController.doPrivileged(new PrivilegedExceptionAction<Boolean>() {
|
return AccessController.doPrivileged((PrivilegedExceptionAction<Boolean>) () ->
|
||||||
@Override
|
handlerType.getMethod(methodName, paramTypes).isAnnotationPresent(ChannelHandler.Skip.class));
|
||||||
public Boolean run() throws Exception {
|
|
||||||
return handlerType.getMethod(methodName, paramTypes).isAnnotationPresent(ChannelHandler.Skip.class);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -280,12 +276,7 @@ abstract class AbstractChannelHandlerContext extends DefaultAttributeMap
|
|||||||
if (executor.inEventLoop()) {
|
if (executor.inEventLoop()) {
|
||||||
next.invokeChannelRegistered();
|
next.invokeChannelRegistered();
|
||||||
} else {
|
} else {
|
||||||
executor.execute(new Runnable() {
|
executor.execute(next::invokeChannelRegistered);
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
next.invokeChannelRegistered();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -312,12 +303,7 @@ abstract class AbstractChannelHandlerContext extends DefaultAttributeMap
|
|||||||
if (executor.inEventLoop()) {
|
if (executor.inEventLoop()) {
|
||||||
next.invokeChannelUnregistered();
|
next.invokeChannelUnregistered();
|
||||||
} else {
|
} else {
|
||||||
executor.execute(new Runnable() {
|
executor.execute(next::invokeChannelUnregistered);
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
next.invokeChannelUnregistered();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -344,12 +330,7 @@ abstract class AbstractChannelHandlerContext extends DefaultAttributeMap
|
|||||||
if (executor.inEventLoop()) {
|
if (executor.inEventLoop()) {
|
||||||
next.invokeChannelActive();
|
next.invokeChannelActive();
|
||||||
} else {
|
} else {
|
||||||
executor.execute(new Runnable() {
|
executor.execute(next::invokeChannelActive);
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
next.invokeChannelActive();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -376,12 +357,7 @@ abstract class AbstractChannelHandlerContext extends DefaultAttributeMap
|
|||||||
if (executor.inEventLoop()) {
|
if (executor.inEventLoop()) {
|
||||||
next.invokeChannelInactive();
|
next.invokeChannelInactive();
|
||||||
} else {
|
} else {
|
||||||
executor.execute(new Runnable() {
|
executor.execute(next::invokeChannelInactive);
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
next.invokeChannelInactive();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -410,12 +386,7 @@ abstract class AbstractChannelHandlerContext extends DefaultAttributeMap
|
|||||||
next.invokeExceptionCaught(cause);
|
next.invokeExceptionCaught(cause);
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
executor.execute(new Runnable() {
|
executor.execute(() -> next.invokeExceptionCaught(cause));
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
next.invokeExceptionCaught(cause);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
if (logger.isWarnEnabled()) {
|
if (logger.isWarnEnabled()) {
|
||||||
logger.warn("Failed to submit an exceptionCaught() event.", t);
|
logger.warn("Failed to submit an exceptionCaught() event.", t);
|
||||||
@ -460,12 +431,7 @@ abstract class AbstractChannelHandlerContext extends DefaultAttributeMap
|
|||||||
if (executor.inEventLoop()) {
|
if (executor.inEventLoop()) {
|
||||||
next.invokeUserEventTriggered(event);
|
next.invokeUserEventTriggered(event);
|
||||||
} else {
|
} else {
|
||||||
executor.execute(new Runnable() {
|
executor.execute(() -> next.invokeUserEventTriggered(event));
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
next.invokeUserEventTriggered(event);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -493,12 +459,7 @@ abstract class AbstractChannelHandlerContext extends DefaultAttributeMap
|
|||||||
if (executor.inEventLoop()) {
|
if (executor.inEventLoop()) {
|
||||||
next.invokeChannelRead(m);
|
next.invokeChannelRead(m);
|
||||||
} else {
|
} else {
|
||||||
executor.execute(new Runnable() {
|
executor.execute(() -> next.invokeChannelRead(m));
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
next.invokeChannelRead(m);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -527,12 +488,7 @@ abstract class AbstractChannelHandlerContext extends DefaultAttributeMap
|
|||||||
} else {
|
} else {
|
||||||
Runnable task = next.invokeChannelReadCompleteTask;
|
Runnable task = next.invokeChannelReadCompleteTask;
|
||||||
if (task == null) {
|
if (task == null) {
|
||||||
next.invokeChannelReadCompleteTask = task = new Runnable() {
|
next.invokeChannelReadCompleteTask = task = next::invokeChannelReadComplete;
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
next.invokeChannelReadComplete();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
executor.execute(task);
|
executor.execute(task);
|
||||||
}
|
}
|
||||||
@ -563,12 +519,7 @@ abstract class AbstractChannelHandlerContext extends DefaultAttributeMap
|
|||||||
} else {
|
} else {
|
||||||
Runnable task = next.invokeChannelWritableStateChangedTask;
|
Runnable task = next.invokeChannelWritableStateChangedTask;
|
||||||
if (task == null) {
|
if (task == null) {
|
||||||
next.invokeChannelWritableStateChangedTask = task = new Runnable() {
|
next.invokeChannelWritableStateChangedTask = task = next::invokeChannelWritabilityChanged;
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
next.invokeChannelWritabilityChanged();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
executor.execute(task);
|
executor.execute(task);
|
||||||
}
|
}
|
||||||
@ -636,12 +587,7 @@ abstract class AbstractChannelHandlerContext extends DefaultAttributeMap
|
|||||||
if (executor.inEventLoop()) {
|
if (executor.inEventLoop()) {
|
||||||
next.invokeBind(localAddress, promise);
|
next.invokeBind(localAddress, promise);
|
||||||
} else {
|
} else {
|
||||||
safeExecute(executor, new Runnable() {
|
safeExecute(executor, () -> next.invokeBind(localAddress, promise), promise, null);
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
next.invokeBind(localAddress, promise);
|
|
||||||
}
|
|
||||||
}, promise, null);
|
|
||||||
}
|
}
|
||||||
return promise;
|
return promise;
|
||||||
}
|
}
|
||||||
@ -680,12 +626,7 @@ abstract class AbstractChannelHandlerContext extends DefaultAttributeMap
|
|||||||
if (executor.inEventLoop()) {
|
if (executor.inEventLoop()) {
|
||||||
next.invokeConnect(remoteAddress, localAddress, promise);
|
next.invokeConnect(remoteAddress, localAddress, promise);
|
||||||
} else {
|
} else {
|
||||||
safeExecute(executor, new Runnable() {
|
safeExecute(executor, () -> next.invokeConnect(remoteAddress, localAddress, promise), promise, null);
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
next.invokeConnect(remoteAddress, localAddress, promise);
|
|
||||||
}
|
|
||||||
}, promise, null);
|
|
||||||
}
|
}
|
||||||
return promise;
|
return promise;
|
||||||
}
|
}
|
||||||
@ -720,14 +661,11 @@ abstract class AbstractChannelHandlerContext extends DefaultAttributeMap
|
|||||||
next.invokeDisconnect(promise);
|
next.invokeDisconnect(promise);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
safeExecute(executor, new Runnable() {
|
safeExecute(executor, () -> {
|
||||||
@Override
|
if (!channel().metadata().hasDisconnect()) {
|
||||||
public void run() {
|
next.invokeClose(promise);
|
||||||
if (!channel().metadata().hasDisconnect()) {
|
} else {
|
||||||
next.invokeClose(promise);
|
next.invokeDisconnect(promise);
|
||||||
} else {
|
|
||||||
next.invokeDisconnect(promise);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}, promise, null);
|
}, promise, null);
|
||||||
}
|
}
|
||||||
@ -758,12 +696,7 @@ abstract class AbstractChannelHandlerContext extends DefaultAttributeMap
|
|||||||
if (executor.inEventLoop()) {
|
if (executor.inEventLoop()) {
|
||||||
next.invokeClose(promise);
|
next.invokeClose(promise);
|
||||||
} else {
|
} else {
|
||||||
safeExecute(executor, new Runnable() {
|
safeExecute(executor, () -> next.invokeClose(promise), promise, null);
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
next.invokeClose(promise);
|
|
||||||
}
|
|
||||||
}, promise, null);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return promise;
|
return promise;
|
||||||
@ -793,12 +726,7 @@ abstract class AbstractChannelHandlerContext extends DefaultAttributeMap
|
|||||||
if (executor.inEventLoop()) {
|
if (executor.inEventLoop()) {
|
||||||
next.invokeRegister(promise);
|
next.invokeRegister(promise);
|
||||||
} else {
|
} else {
|
||||||
safeExecute(executor, new Runnable() {
|
safeExecute(executor, () -> next.invokeRegister(promise), promise, null);
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
next.invokeRegister(promise);
|
|
||||||
}
|
|
||||||
}, promise, null);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return promise;
|
return promise;
|
||||||
@ -828,12 +756,7 @@ abstract class AbstractChannelHandlerContext extends DefaultAttributeMap
|
|||||||
if (executor.inEventLoop()) {
|
if (executor.inEventLoop()) {
|
||||||
next.invokeDeregister(promise);
|
next.invokeDeregister(promise);
|
||||||
} else {
|
} else {
|
||||||
safeExecute(executor, new Runnable() {
|
safeExecute(executor, () -> next.invokeDeregister(promise), promise, null);
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
next.invokeDeregister(promise);
|
|
||||||
}
|
|
||||||
}, promise, null);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return promise;
|
return promise;
|
||||||
@ -860,12 +783,7 @@ abstract class AbstractChannelHandlerContext extends DefaultAttributeMap
|
|||||||
} else {
|
} else {
|
||||||
Runnable task = next.invokeReadTask;
|
Runnable task = next.invokeReadTask;
|
||||||
if (task == null) {
|
if (task == null) {
|
||||||
next.invokeReadTask = task = new Runnable() {
|
next.invokeReadTask = task = next::invokeRead;
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
next.invokeRead();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
executor.execute(task);
|
executor.execute(task);
|
||||||
}
|
}
|
||||||
@ -922,12 +840,7 @@ abstract class AbstractChannelHandlerContext extends DefaultAttributeMap
|
|||||||
} else {
|
} else {
|
||||||
Runnable task = next.invokeFlushTask;
|
Runnable task = next.invokeFlushTask;
|
||||||
if (task == null) {
|
if (task == null) {
|
||||||
next.invokeFlushTask = task = new Runnable() {
|
next.invokeFlushTask = task = next::invokeFlush;
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
next.invokeFlush();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
safeExecute(executor, task, channel().voidPromise(), null);
|
safeExecute(executor, task, channel().voidPromise(), null);
|
||||||
}
|
}
|
||||||
|
@ -38,23 +38,15 @@ public interface ChannelFutureListener extends GenericFutureListener<ChannelFutu
|
|||||||
* A {@link ChannelFutureListener} that closes the {@link Channel} which is
|
* A {@link ChannelFutureListener} that closes the {@link Channel} which is
|
||||||
* associated with the specified {@link ChannelFuture}.
|
* associated with the specified {@link ChannelFuture}.
|
||||||
*/
|
*/
|
||||||
ChannelFutureListener CLOSE = new ChannelFutureListener() {
|
ChannelFutureListener CLOSE = future -> future.channel().close();
|
||||||
@Override
|
|
||||||
public void operationComplete(ChannelFuture future) {
|
|
||||||
future.channel().close();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A {@link ChannelFutureListener} that closes the {@link Channel} when the
|
* A {@link ChannelFutureListener} that closes the {@link Channel} when the
|
||||||
* operation ended up with a failure or cancellation rather than a success.
|
* operation ended up with a failure or cancellation rather than a success.
|
||||||
*/
|
*/
|
||||||
ChannelFutureListener CLOSE_ON_FAILURE = new ChannelFutureListener() {
|
ChannelFutureListener CLOSE_ON_FAILURE = future -> {
|
||||||
@Override
|
if (!future.isSuccess()) {
|
||||||
public void operationComplete(ChannelFuture future) {
|
future.channel().close();
|
||||||
if (!future.isSuccess()) {
|
|
||||||
future.channel().close();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -62,12 +54,9 @@ public interface ChannelFutureListener extends GenericFutureListener<ChannelFutu
|
|||||||
* A {@link ChannelFutureListener} that forwards the {@link Throwable} of the {@link ChannelFuture} into the
|
* A {@link ChannelFutureListener} that forwards the {@link Throwable} of the {@link ChannelFuture} into the
|
||||||
* {@link ChannelPipeline}. This mimics the old behavior of Netty 3.
|
* {@link ChannelPipeline}. This mimics the old behavior of Netty 3.
|
||||||
*/
|
*/
|
||||||
ChannelFutureListener FIRE_EXCEPTION_ON_FAILURE = new ChannelFutureListener() {
|
ChannelFutureListener FIRE_EXCEPTION_ON_FAILURE = future -> {
|
||||||
@Override
|
if (!future.isSuccess()) {
|
||||||
public void operationComplete(ChannelFuture future) {
|
future.channel().pipeline().fireExceptionCaught(future.cause());
|
||||||
if (!future.isSuccess()) {
|
|
||||||
future.channel().pipeline().fireExceptionCaught(future.cause());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -602,12 +602,7 @@ public final class ChannelOutboundBuffer {
|
|||||||
if (invokeLater) {
|
if (invokeLater) {
|
||||||
Runnable task = fireChannelWritabilityChangedTask;
|
Runnable task = fireChannelWritabilityChangedTask;
|
||||||
if (task == null) {
|
if (task == null) {
|
||||||
fireChannelWritabilityChangedTask = task = new Runnable() {
|
fireChannelWritabilityChangedTask = task = pipeline::fireChannelWritabilityChanged;
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
pipeline.fireChannelWritabilityChanged();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
channel.eventLoop().execute(task);
|
channel.eventLoop().execute(task);
|
||||||
} else {
|
} else {
|
||||||
@ -654,12 +649,7 @@ public final class ChannelOutboundBuffer {
|
|||||||
|
|
||||||
void close(final Throwable cause, final boolean allowChannelOpen) {
|
void close(final Throwable cause, final boolean allowChannelOpen) {
|
||||||
if (inFail) {
|
if (inFail) {
|
||||||
channel.eventLoop().execute(new Runnable() {
|
channel.eventLoop().execute(() -> close(cause, allowChannelOpen));
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
close(cause, allowChannelOpen);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -614,12 +614,7 @@ public class CombinedChannelDuplexHandler<I extends ChannelInboundHandler, O ext
|
|||||||
if (executor.inEventLoop()) {
|
if (executor.inEventLoop()) {
|
||||||
remove0();
|
remove0();
|
||||||
} else {
|
} else {
|
||||||
executor.execute(new Runnable() {
|
executor.execute(this::remove0);
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
remove0();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -123,12 +123,7 @@ public class DefaultChannelPipeline implements ChannelPipeline {
|
|||||||
EventExecutor ctxExecutor = newCtx.executor();
|
EventExecutor ctxExecutor = newCtx.executor();
|
||||||
if (!ctxExecutor.inEventLoop()) {
|
if (!ctxExecutor.inEventLoop()) {
|
||||||
newCtx.setAddPending();
|
newCtx.setAddPending();
|
||||||
ctxExecutor.execute(new Runnable() {
|
ctxExecutor.execute(() -> callHandlerAdded0(newCtx));
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
callHandlerAdded0(newCtx);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -162,12 +157,7 @@ public class DefaultChannelPipeline implements ChannelPipeline {
|
|||||||
EventExecutor ctxExecutor = newCtx.executor();
|
EventExecutor ctxExecutor = newCtx.executor();
|
||||||
if (!ctxExecutor.inEventLoop()) {
|
if (!ctxExecutor.inEventLoop()) {
|
||||||
newCtx.setAddPending();
|
newCtx.setAddPending();
|
||||||
ctxExecutor.execute(new Runnable() {
|
ctxExecutor.execute(() -> callHandlerAdded0(newCtx));
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
callHandlerAdded0(newCtx);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -205,12 +195,7 @@ public class DefaultChannelPipeline implements ChannelPipeline {
|
|||||||
EventExecutor ctxExecutor = newCtx.executor();
|
EventExecutor ctxExecutor = newCtx.executor();
|
||||||
if (!ctxExecutor.inEventLoop()) {
|
if (!ctxExecutor.inEventLoop()) {
|
||||||
newCtx.setAddPending();
|
newCtx.setAddPending();
|
||||||
ctxExecutor.execute(new Runnable() {
|
ctxExecutor.execute(() -> callHandlerAdded0(newCtx));
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
callHandlerAdded0(newCtx);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -256,12 +241,7 @@ public class DefaultChannelPipeline implements ChannelPipeline {
|
|||||||
EventExecutor ctxExecutor = newCtx.executor();
|
EventExecutor ctxExecutor = newCtx.executor();
|
||||||
if (!ctxExecutor.inEventLoop()) {
|
if (!ctxExecutor.inEventLoop()) {
|
||||||
newCtx.setAddPending();
|
newCtx.setAddPending();
|
||||||
ctxExecutor.execute(new Runnable() {
|
ctxExecutor.execute(() -> callHandlerAdded0(newCtx));
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
callHandlerAdded0(newCtx);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -407,12 +387,7 @@ public class DefaultChannelPipeline implements ChannelPipeline {
|
|||||||
|
|
||||||
EventExecutor executor = ctx.executor();
|
EventExecutor executor = ctx.executor();
|
||||||
if (!executor.inEventLoop()) {
|
if (!executor.inEventLoop()) {
|
||||||
executor.execute(new Runnable() {
|
executor.execute(() -> callHandlerRemoved0(ctx));
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
callHandlerRemoved0(ctx);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return ctx;
|
return ctx;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -483,15 +458,12 @@ public class DefaultChannelPipeline implements ChannelPipeline {
|
|||||||
|
|
||||||
EventExecutor executor = ctx.executor();
|
EventExecutor executor = ctx.executor();
|
||||||
if (!executor.inEventLoop()) {
|
if (!executor.inEventLoop()) {
|
||||||
executor.execute(new Runnable() {
|
executor.execute(() -> {
|
||||||
@Override
|
// Invoke newHandler.handlerAdded() first (i.e. before oldHandler.handlerRemoved() is invoked)
|
||||||
public void run() {
|
// because callHandlerRemoved() will trigger channelRead() or flush() on newHandler and
|
||||||
// Invoke newHandler.handlerAdded() first (i.e. before oldHandler.handlerRemoved() is invoked)
|
// those event handlers must be called after handlerAdded().
|
||||||
// because callHandlerRemoved() will trigger channelRead() or flush() on newHandler and
|
callHandlerAdded0(newCtx);
|
||||||
// those event handlers must be called after handlerAdded().
|
callHandlerRemoved0(ctx);
|
||||||
callHandlerAdded0(newCtx);
|
|
||||||
callHandlerRemoved0(ctx);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
return ctx.handler();
|
return ctx.handler();
|
||||||
}
|
}
|
||||||
@ -776,12 +748,7 @@ public class DefaultChannelPipeline implements ChannelPipeline {
|
|||||||
final EventExecutor executor = ctx.executor();
|
final EventExecutor executor = ctx.executor();
|
||||||
if (!inEventLoop && !executor.inEventLoop(currentThread)) {
|
if (!inEventLoop && !executor.inEventLoop(currentThread)) {
|
||||||
final AbstractChannelHandlerContext finalCtx = ctx;
|
final AbstractChannelHandlerContext finalCtx = ctx;
|
||||||
executor.execute(new Runnable() {
|
executor.execute(() -> destroyUp(finalCtx, true));
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
destroyUp(finalCtx, true);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -806,12 +773,7 @@ public class DefaultChannelPipeline implements ChannelPipeline {
|
|||||||
callHandlerRemoved0(ctx);
|
callHandlerRemoved0(ctx);
|
||||||
} else {
|
} else {
|
||||||
final AbstractChannelHandlerContext finalCtx = ctx;
|
final AbstractChannelHandlerContext finalCtx = ctx;
|
||||||
executor.execute(new Runnable() {
|
executor.execute(() -> destroyDown(Thread.currentThread(), finalCtx, true));
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
destroyDown(Thread.currentThread(), finalCtx, true);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,13 +40,10 @@ public final class VoidChannelPromise extends AbstractFuture<Void> implements Ch
|
|||||||
}
|
}
|
||||||
this.channel = channel;
|
this.channel = channel;
|
||||||
if (fireException) {
|
if (fireException) {
|
||||||
fireExceptionListener = new ChannelFutureListener() {
|
fireExceptionListener = future -> {
|
||||||
@Override
|
Throwable cause = future.cause();
|
||||||
public void operationComplete(ChannelFuture future) throws Exception {
|
if (cause != null) {
|
||||||
Throwable cause = future.cause();
|
fireException0(cause);
|
||||||
if (cause != null) {
|
|
||||||
fireException0(cause);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
|
@ -59,12 +59,7 @@ public class EmbeddedChannel extends AbstractChannel {
|
|||||||
private static final ChannelMetadata METADATA_NO_DISCONNECT = new ChannelMetadata(false);
|
private static final ChannelMetadata METADATA_NO_DISCONNECT = new ChannelMetadata(false);
|
||||||
private static final ChannelMetadata METADATA_DISCONNECT = new ChannelMetadata(true);
|
private static final ChannelMetadata METADATA_DISCONNECT = new ChannelMetadata(true);
|
||||||
|
|
||||||
private final ChannelFutureListener recordExceptionListener = new ChannelFutureListener() {
|
private final ChannelFutureListener recordExceptionListener = this::recordException;
|
||||||
@Override
|
|
||||||
public void operationComplete(ChannelFuture future) throws Exception {
|
|
||||||
recordException(future);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
private final ChannelMetadata metadata;
|
private final ChannelMetadata metadata;
|
||||||
private final ChannelConfig config;
|
private final ChannelConfig config;
|
||||||
|
@ -23,12 +23,7 @@ import io.netty.channel.ServerChannel;
|
|||||||
*/
|
*/
|
||||||
public final class ChannelMatchers {
|
public final class ChannelMatchers {
|
||||||
|
|
||||||
private static final ChannelMatcher ALL_MATCHER = new ChannelMatcher() {
|
private static final ChannelMatcher ALL_MATCHER = channel -> true;
|
||||||
@Override
|
|
||||||
public boolean matches(Channel channel) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
private static final ChannelMatcher SERVER_CHANNEL_MATCHER = isInstanceOf(ServerChannel.class);
|
private static final ChannelMatcher SERVER_CHANNEL_MATCHER = isInstanceOf(ServerChannel.class);
|
||||||
private static final ChannelMatcher NON_SERVER_CHANNEL_MATCHER = isNotInstanceOf(ServerChannel.class);
|
private static final ChannelMatcher NON_SERVER_CHANNEL_MATCHER = isNotInstanceOf(ServerChannel.class);
|
||||||
|
@ -46,12 +46,7 @@ public class DefaultChannelGroup extends AbstractSet<Channel> implements Channel
|
|||||||
private final EventExecutor executor;
|
private final EventExecutor executor;
|
||||||
private final ConcurrentMap<ChannelId, Channel> serverChannels = new ConcurrentHashMap<>();
|
private final ConcurrentMap<ChannelId, Channel> serverChannels = new ConcurrentHashMap<>();
|
||||||
private final ConcurrentMap<ChannelId, Channel> nonServerChannels = new ConcurrentHashMap<>();
|
private final ConcurrentMap<ChannelId, Channel> nonServerChannels = new ConcurrentHashMap<>();
|
||||||
private final ChannelFutureListener remover = new ChannelFutureListener() {
|
private final ChannelFutureListener remover = future -> remove(future.channel());
|
||||||
@Override
|
|
||||||
public void operationComplete(ChannelFuture future) throws Exception {
|
|
||||||
remove(future.channel());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
private final VoidChannelGroupFuture voidFuture = new VoidChannelGroupFuture(this);
|
private final VoidChannelGroupFuture voidFuture = new VoidChannelGroupFuture(this);
|
||||||
private final boolean stayClosed;
|
private final boolean stayClosed;
|
||||||
private volatile boolean closed;
|
private volatile boolean closed;
|
||||||
|
@ -63,13 +63,10 @@ public class LocalChannel extends AbstractChannel {
|
|||||||
private final ChannelConfig config = new DefaultChannelConfig(this);
|
private final ChannelConfig config = new DefaultChannelConfig(this);
|
||||||
// To further optimize this we could write our own SPSC queue.
|
// To further optimize this we could write our own SPSC queue.
|
||||||
final Queue<Object> inboundBuffer = PlatformDependent.newSpscQueue();
|
final Queue<Object> inboundBuffer = PlatformDependent.newSpscQueue();
|
||||||
private final Runnable readTask = new Runnable() {
|
private final Runnable readTask = () -> {
|
||||||
@Override
|
// Ensure the inboundBuffer is not empty as readInbound() will always call fireChannelReadComplete()
|
||||||
public void run() {
|
if (!inboundBuffer.isEmpty()) {
|
||||||
// Ensure the inboundBuffer is not empty as readInbound() will always call fireChannelReadComplete()
|
readInbound();
|
||||||
if (!inboundBuffer.isEmpty()) {
|
|
||||||
readInbound();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -197,12 +194,7 @@ public class LocalChannel extends AbstractChannel {
|
|||||||
EventLoop peerEventLoop = peer.eventLoop();
|
EventLoop peerEventLoop = peer.eventLoop();
|
||||||
final boolean peerIsActive = peer.isActive();
|
final boolean peerIsActive = peer.isActive();
|
||||||
try {
|
try {
|
||||||
peerEventLoop.execute(new Runnable() {
|
peerEventLoop.execute(() -> peer.tryClose(peerIsActive));
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
peer.tryClose(peerIsActive);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} catch (Throwable cause) {
|
} catch (Throwable cause) {
|
||||||
logger.warn("Releasing Inbound Queues for channels {}-{} because exception occurred!",
|
logger.warn("Releasing Inbound Queues for channels {}-{} because exception occurred!",
|
||||||
this, peer, cause);
|
this, peer, cause);
|
||||||
@ -350,12 +342,7 @@ public class LocalChannel extends AbstractChannel {
|
|||||||
private void runFinishPeerReadTask(final LocalChannel peer) {
|
private void runFinishPeerReadTask(final LocalChannel peer) {
|
||||||
// If the peer is writing, we must wait until after reads are completed for that peer before we can read. So
|
// If the peer is writing, we must wait until after reads are completed for that peer before we can read. So
|
||||||
// we keep track of the task, and coordinate later that our read can't happen until the peer is done.
|
// we keep track of the task, and coordinate later that our read can't happen until the peer is done.
|
||||||
final Runnable finishPeerReadTask = new Runnable() {
|
final Runnable finishPeerReadTask = () -> finishPeerRead0(peer);
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
finishPeerRead0(peer);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
try {
|
try {
|
||||||
if (peer.writeInProgress) {
|
if (peer.writeInProgress) {
|
||||||
peer.finishReadFuture = peer.eventLoop().submit(finishPeerReadTask);
|
peer.finishReadFuture = peer.eventLoop().submit(finishPeerReadTask);
|
||||||
@ -470,17 +457,14 @@ public class LocalChannel extends AbstractChannel {
|
|||||||
// This ensures that if both channels are on the same event loop, the peer's channelActive
|
// This ensures that if both channels are on the same event loop, the peer's channelActive
|
||||||
// event is triggered *after* this channel's channelRegistered event, so that this channel's
|
// event is triggered *after* this channel's channelRegistered event, so that this channel's
|
||||||
// pipeline is fully initialized by ChannelInitializer before any channelRead events.
|
// pipeline is fully initialized by ChannelInitializer before any channelRead events.
|
||||||
peer.eventLoop().execute(new Runnable() {
|
peer.eventLoop().execute(() -> {
|
||||||
@Override
|
ChannelPromise promise = peer.connectPromise;
|
||||||
public void run() {
|
|
||||||
ChannelPromise promise = peer.connectPromise;
|
|
||||||
|
|
||||||
// Only trigger fireChannelActive() if the promise was not null and was not completed yet.
|
// Only trigger fireChannelActive() if the promise was not null and was not completed yet.
|
||||||
// connectPromise may be set to null if doClose() was called in the meantime.
|
// connectPromise may be set to null if doClose() was called in the meantime.
|
||||||
if (promise != null && promise.trySuccess()) {
|
if (promise != null && promise.trySuccess()) {
|
||||||
peer.pipeline().fireChannelActive();
|
peer.pipeline().fireChannelActive();
|
||||||
peer.readIfIsAutoRead();
|
peer.readIfIsAutoRead();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -38,12 +38,7 @@ public final class LocalHandler implements IoHandler {
|
|||||||
* Returns a new {@link IoHandlerFactory} that creates {@link LocalHandler} instances.
|
* Returns a new {@link IoHandlerFactory} that creates {@link LocalHandler} instances.
|
||||||
*/
|
*/
|
||||||
public static IoHandlerFactory newFactory() {
|
public static IoHandlerFactory newFactory() {
|
||||||
return new IoHandlerFactory() {
|
return LocalHandler::new;
|
||||||
@Override
|
|
||||||
public IoHandler newHandler() {
|
|
||||||
return new LocalHandler();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static LocalChannelUnsafe cast(Channel channel) {
|
private static LocalChannelUnsafe cast(Channel channel) {
|
||||||
|
@ -115,12 +115,7 @@ public class LocalServerChannel extends AbstractServerChannel {
|
|||||||
if (eventLoop().inEventLoop()) {
|
if (eventLoop().inEventLoop()) {
|
||||||
serve0(child);
|
serve0(child);
|
||||||
} else {
|
} else {
|
||||||
eventLoop().execute(new Runnable() {
|
eventLoop().execute(() -> serve0(child));
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
serve0(child);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
return child;
|
return child;
|
||||||
}
|
}
|
||||||
|
@ -47,13 +47,10 @@ public abstract class AbstractNioByteChannel extends AbstractNioChannel {
|
|||||||
" (expected: " + StringUtil.simpleClassName(ByteBuf.class) + ", " +
|
" (expected: " + StringUtil.simpleClassName(ByteBuf.class) + ", " +
|
||||||
StringUtil.simpleClassName(FileRegion.class) + ')';
|
StringUtil.simpleClassName(FileRegion.class) + ')';
|
||||||
|
|
||||||
private final Runnable flushTask = new Runnable() {
|
private final Runnable flushTask = () -> {
|
||||||
@Override
|
// Calling flush0 directly to ensure we not try to flush messages that were added via write(...) in the
|
||||||
public void run() {
|
// meantime.
|
||||||
// Calling flush0 directly to ensure we not try to flush messages that were added via write(...) in the
|
((AbstractNioUnsafe) unsafe()).flush0();
|
||||||
// meantime.
|
|
||||||
((AbstractNioUnsafe) unsafe()).flush0();
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
private boolean inputClosedSeenErrorOnRead;
|
private boolean inputClosedSeenErrorOnRead;
|
||||||
|
|
||||||
|
@ -57,12 +57,7 @@ public abstract class AbstractNioChannel extends AbstractChannel {
|
|||||||
protected final int readInterestOp;
|
protected final int readInterestOp;
|
||||||
volatile SelectionKey selectionKey;
|
volatile SelectionKey selectionKey;
|
||||||
boolean readPending;
|
boolean readPending;
|
||||||
private final Runnable clearReadPendingRunnable = new Runnable() {
|
private final Runnable clearReadPendingRunnable = this::clearReadPending0;
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
clearReadPending0();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The future of the current connection attempt. If not null, subsequent
|
* The future of the current connection attempt. If not null, subsequent
|
||||||
@ -142,12 +137,7 @@ public abstract class AbstractNioChannel extends AbstractChannel {
|
|||||||
if (eventLoop.inEventLoop()) {
|
if (eventLoop.inEventLoop()) {
|
||||||
setReadPending0(readPending);
|
setReadPending0(readPending);
|
||||||
} else {
|
} else {
|
||||||
eventLoop.execute(new Runnable() {
|
eventLoop.execute(() -> setReadPending0(readPending));
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
setReadPending0(readPending);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Best effort if we are not registered yet clear readPending.
|
// Best effort if we are not registered yet clear readPending.
|
||||||
@ -255,29 +245,23 @@ public abstract class AbstractNioChannel extends AbstractChannel {
|
|||||||
// Schedule connect timeout.
|
// Schedule connect timeout.
|
||||||
int connectTimeoutMillis = config().getConnectTimeoutMillis();
|
int connectTimeoutMillis = config().getConnectTimeoutMillis();
|
||||||
if (connectTimeoutMillis > 0) {
|
if (connectTimeoutMillis > 0) {
|
||||||
connectTimeoutFuture = eventLoop().schedule(new Runnable() {
|
connectTimeoutFuture = eventLoop().schedule(() -> {
|
||||||
@Override
|
ChannelPromise connectPromise = AbstractNioChannel.this.connectPromise;
|
||||||
public void run() {
|
ConnectTimeoutException cause =
|
||||||
ChannelPromise connectPromise = AbstractNioChannel.this.connectPromise;
|
new ConnectTimeoutException("connection timed out: " + remoteAddress);
|
||||||
ConnectTimeoutException cause =
|
if (connectPromise != null && connectPromise.tryFailure(cause)) {
|
||||||
new ConnectTimeoutException("connection timed out: " + remoteAddress);
|
close(voidPromise());
|
||||||
if (connectPromise != null && connectPromise.tryFailure(cause)) {
|
|
||||||
close(voidPromise());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}, connectTimeoutMillis, TimeUnit.MILLISECONDS);
|
}, connectTimeoutMillis, TimeUnit.MILLISECONDS);
|
||||||
}
|
}
|
||||||
|
|
||||||
promise.addListener(new ChannelFutureListener() {
|
promise.addListener((ChannelFutureListener) future -> {
|
||||||
@Override
|
if (future.isCancelled()) {
|
||||||
public void operationComplete(ChannelFuture future) throws Exception {
|
if (connectTimeoutFuture != null) {
|
||||||
if (future.isCancelled()) {
|
connectTimeoutFuture.cancel(false);
|
||||||
if (connectTimeoutFuture != null) {
|
|
||||||
connectTimeoutFuture.cancel(false);
|
|
||||||
}
|
|
||||||
connectPromise = null;
|
|
||||||
close(voidPromise());
|
|
||||||
}
|
}
|
||||||
|
connectPromise = null;
|
||||||
|
close(voidPromise());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -67,12 +67,7 @@ public final class NioHandler implements IoHandler {
|
|||||||
private static final int MIN_PREMATURE_SELECTOR_RETURNS = 3;
|
private static final int MIN_PREMATURE_SELECTOR_RETURNS = 3;
|
||||||
private static final int SELECTOR_AUTO_REBUILD_THRESHOLD;
|
private static final int SELECTOR_AUTO_REBUILD_THRESHOLD;
|
||||||
|
|
||||||
private final IntSupplier selectNowSupplier = new IntSupplier() {
|
private final IntSupplier selectNowSupplier = this::selectNow;
|
||||||
@Override
|
|
||||||
public int get() throws Exception {
|
|
||||||
return selectNow();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Workaround for JDK NIO bug.
|
// Workaround for JDK NIO bug.
|
||||||
//
|
//
|
||||||
@ -84,12 +79,9 @@ public final class NioHandler implements IoHandler {
|
|||||||
final String bugLevel = SystemPropertyUtil.get(key);
|
final String bugLevel = SystemPropertyUtil.get(key);
|
||||||
if (bugLevel == null) {
|
if (bugLevel == null) {
|
||||||
try {
|
try {
|
||||||
AccessController.doPrivileged(new PrivilegedAction<Void>() {
|
AccessController.doPrivileged((PrivilegedAction<Void>) () -> {
|
||||||
@Override
|
System.setProperty(key, "");
|
||||||
public Void run() {
|
return null;
|
||||||
System.setProperty(key, "");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
} catch (final SecurityException e) {
|
} catch (final SecurityException e) {
|
||||||
logger.debug("Unable to get/set System Property: " + key, e);
|
logger.debug("Unable to get/set System Property: " + key, e);
|
||||||
@ -147,12 +139,7 @@ public final class NioHandler implements IoHandler {
|
|||||||
* Returns a new {@link IoHandlerFactory} that creates {@link NioHandler} instances.
|
* Returns a new {@link IoHandlerFactory} that creates {@link NioHandler} instances.
|
||||||
*/
|
*/
|
||||||
public static IoHandlerFactory newFactory() {
|
public static IoHandlerFactory newFactory() {
|
||||||
return new IoHandlerFactory() {
|
return NioHandler::new;
|
||||||
@Override
|
|
||||||
public IoHandler newHandler() {
|
|
||||||
return new NioHandler();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -162,12 +149,7 @@ public final class NioHandler implements IoHandler {
|
|||||||
final SelectStrategyFactory selectStrategyFactory) {
|
final SelectStrategyFactory selectStrategyFactory) {
|
||||||
ObjectUtil.checkNotNull(selectorProvider, "selectorProvider");
|
ObjectUtil.checkNotNull(selectorProvider, "selectorProvider");
|
||||||
ObjectUtil.checkNotNull(selectStrategyFactory, "selectStrategyFactory");
|
ObjectUtil.checkNotNull(selectStrategyFactory, "selectStrategyFactory");
|
||||||
return new IoHandlerFactory() {
|
return () -> new NioHandler(selectorProvider, selectStrategyFactory.newSelectStrategy());
|
||||||
@Override
|
|
||||||
public IoHandler newHandler() {
|
|
||||||
return new NioHandler(selectorProvider, selectStrategyFactory.newSelectStrategy());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final class SelectorTuple {
|
private static final class SelectorTuple {
|
||||||
@ -197,17 +179,14 @@ public final class NioHandler implements IoHandler {
|
|||||||
return new SelectorTuple(unwrappedSelector);
|
return new SelectorTuple(unwrappedSelector);
|
||||||
}
|
}
|
||||||
|
|
||||||
Object maybeSelectorImplClass = AccessController.doPrivileged(new PrivilegedAction<Object>() {
|
Object maybeSelectorImplClass = AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
|
||||||
@Override
|
try {
|
||||||
public Object run() {
|
return Class.forName(
|
||||||
try {
|
"sun.nio.ch.SelectorImpl",
|
||||||
return Class.forName(
|
false,
|
||||||
"sun.nio.ch.SelectorImpl",
|
PlatformDependent.getSystemClassLoader());
|
||||||
false,
|
} catch (Throwable cause) {
|
||||||
PlatformDependent.getSystemClassLoader());
|
return cause;
|
||||||
} catch (Throwable cause) {
|
|
||||||
return cause;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -224,45 +203,42 @@ public final class NioHandler implements IoHandler {
|
|||||||
final Class<?> selectorImplClass = (Class<?>) maybeSelectorImplClass;
|
final Class<?> selectorImplClass = (Class<?>) maybeSelectorImplClass;
|
||||||
final SelectedSelectionKeySet selectedKeySet = new SelectedSelectionKeySet();
|
final SelectedSelectionKeySet selectedKeySet = new SelectedSelectionKeySet();
|
||||||
|
|
||||||
Object maybeException = AccessController.doPrivileged(new PrivilegedAction<Object>() {
|
Object maybeException = AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
|
||||||
@Override
|
try {
|
||||||
public Object run() {
|
Field selectedKeysField = selectorImplClass.getDeclaredField("selectedKeys");
|
||||||
try {
|
Field publicSelectedKeysField = selectorImplClass.getDeclaredField("publicSelectedKeys");
|
||||||
Field selectedKeysField = selectorImplClass.getDeclaredField("selectedKeys");
|
|
||||||
Field publicSelectedKeysField = selectorImplClass.getDeclaredField("publicSelectedKeys");
|
|
||||||
|
|
||||||
if (PlatformDependent.javaVersion() >= 9 && PlatformDependent.hasUnsafe()) {
|
if (PlatformDependent.javaVersion() >= 9 && PlatformDependent.hasUnsafe()) {
|
||||||
// Let us try to use sun.misc.Unsafe to replace the SelectionKeySet.
|
// 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.
|
// This allows us to also do this in Java9+ without any extra flags.
|
||||||
long selectedKeysFieldOffset = PlatformDependent.objectFieldOffset(selectedKeysField);
|
long selectedKeysFieldOffset = PlatformDependent.objectFieldOffset(selectedKeysField);
|
||||||
long publicSelectedKeysFieldOffset =
|
long publicSelectedKeysFieldOffset =
|
||||||
PlatformDependent.objectFieldOffset(publicSelectedKeysField);
|
PlatformDependent.objectFieldOffset(publicSelectedKeysField);
|
||||||
|
|
||||||
if (selectedKeysFieldOffset != -1 && publicSelectedKeysFieldOffset != -1) {
|
if (selectedKeysFieldOffset != -1 && publicSelectedKeysFieldOffset != -1) {
|
||||||
PlatformDependent.putObject(
|
PlatformDependent.putObject(
|
||||||
unwrappedSelector, selectedKeysFieldOffset, selectedKeySet);
|
unwrappedSelector, selectedKeysFieldOffset, selectedKeySet);
|
||||||
PlatformDependent.putObject(
|
PlatformDependent.putObject(
|
||||||
unwrappedSelector, publicSelectedKeysFieldOffset, selectedKeySet);
|
unwrappedSelector, publicSelectedKeysFieldOffset, selectedKeySet);
|
||||||
return null;
|
return null;
|
||||||
}
|
|
||||||
// We could not retrieve the offset, lets try reflection as last-resort.
|
|
||||||
}
|
}
|
||||||
|
// 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) {
|
|
||||||
return e;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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) {
|
||||||
|
return e;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -170,12 +170,7 @@ public class NioSocketChannel extends AbstractNioByteChannel implements io.netty
|
|||||||
if (loop.inEventLoop()) {
|
if (loop.inEventLoop()) {
|
||||||
((AbstractUnsafe) unsafe()).shutdownOutput(promise);
|
((AbstractUnsafe) unsafe()).shutdownOutput(promise);
|
||||||
} else {
|
} else {
|
||||||
loop.execute(new Runnable() {
|
loop.execute(() -> ((AbstractUnsafe) unsafe()).shutdownOutput(promise));
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
((AbstractUnsafe) unsafe()).shutdownOutput(promise);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
return promise;
|
return promise;
|
||||||
}
|
}
|
||||||
@ -196,12 +191,7 @@ public class NioSocketChannel extends AbstractNioByteChannel implements io.netty
|
|||||||
if (loop.inEventLoop()) {
|
if (loop.inEventLoop()) {
|
||||||
shutdownInput0(promise);
|
shutdownInput0(promise);
|
||||||
} else {
|
} else {
|
||||||
loop.execute(new Runnable() {
|
loop.execute(() -> shutdownInput0(promise));
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
shutdownInput0(promise);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
return promise;
|
return promise;
|
||||||
}
|
}
|
||||||
@ -217,12 +207,8 @@ public class NioSocketChannel extends AbstractNioByteChannel implements io.netty
|
|||||||
if (shutdownOutputFuture.isDone()) {
|
if (shutdownOutputFuture.isDone()) {
|
||||||
shutdownOutputDone(shutdownOutputFuture, promise);
|
shutdownOutputDone(shutdownOutputFuture, promise);
|
||||||
} else {
|
} else {
|
||||||
shutdownOutputFuture.addListener(new ChannelFutureListener() {
|
shutdownOutputFuture.addListener((ChannelFutureListener) shutdownOutputFuture1 ->
|
||||||
@Override
|
shutdownOutputDone(shutdownOutputFuture1, promise));
|
||||||
public void operationComplete(final ChannelFuture shutdownOutputFuture) throws Exception {
|
|
||||||
shutdownOutputDone(shutdownOutputFuture, promise);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
return promise;
|
return promise;
|
||||||
}
|
}
|
||||||
@ -232,12 +218,8 @@ public class NioSocketChannel extends AbstractNioByteChannel implements io.netty
|
|||||||
if (shutdownInputFuture.isDone()) {
|
if (shutdownInputFuture.isDone()) {
|
||||||
shutdownDone(shutdownOutputFuture, shutdownInputFuture, promise);
|
shutdownDone(shutdownOutputFuture, shutdownInputFuture, promise);
|
||||||
} else {
|
} else {
|
||||||
shutdownInputFuture.addListener(new ChannelFutureListener() {
|
shutdownInputFuture.addListener((ChannelFutureListener) shutdownInputFuture1 ->
|
||||||
@Override
|
shutdownDone(shutdownOutputFuture, shutdownInputFuture1, promise));
|
||||||
public void operationComplete(ChannelFuture shutdownInputFuture) throws Exception {
|
|
||||||
shutdownDone(shutdownOutputFuture, shutdownInputFuture, promise);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,8 +16,6 @@
|
|||||||
|
|
||||||
package io.netty.bootstrap;
|
package io.netty.bootstrap;
|
||||||
|
|
||||||
import io.netty.channel.Channel;
|
|
||||||
import io.netty.channel.ChannelFactory;
|
|
||||||
import io.netty.channel.ChannelFuture;
|
import io.netty.channel.ChannelFuture;
|
||||||
import io.netty.channel.ChannelFutureListener;
|
import io.netty.channel.ChannelFutureListener;
|
||||||
import io.netty.channel.ChannelHandler.Sharable;
|
import io.netty.channel.ChannelHandler.Sharable;
|
||||||
@ -26,18 +24,15 @@ import io.netty.channel.ChannelInboundHandler;
|
|||||||
import io.netty.channel.ChannelInboundHandlerAdapter;
|
import io.netty.channel.ChannelInboundHandlerAdapter;
|
||||||
import io.netty.channel.ChannelOutboundHandlerAdapter;
|
import io.netty.channel.ChannelOutboundHandlerAdapter;
|
||||||
import io.netty.channel.ChannelPromise;
|
import io.netty.channel.ChannelPromise;
|
||||||
import io.netty.channel.MultithreadEventLoopGroup;
|
|
||||||
import io.netty.channel.EventLoop;
|
|
||||||
import io.netty.channel.EventLoopGroup;
|
import io.netty.channel.EventLoopGroup;
|
||||||
import io.netty.channel.ServerChannel;
|
import io.netty.channel.MultithreadEventLoopGroup;
|
||||||
import io.netty.channel.ServerChannelFactory;
|
|
||||||
import io.netty.channel.local.LocalAddress;
|
import io.netty.channel.local.LocalAddress;
|
||||||
import io.netty.channel.local.LocalChannel;
|
import io.netty.channel.local.LocalChannel;
|
||||||
import io.netty.channel.local.LocalHandler;
|
import io.netty.channel.local.LocalHandler;
|
||||||
import io.netty.channel.local.LocalServerChannel;
|
import io.netty.channel.local.LocalServerChannel;
|
||||||
|
import io.netty.resolver.AbstractAddressResolver;
|
||||||
import io.netty.resolver.AddressResolver;
|
import io.netty.resolver.AddressResolver;
|
||||||
import io.netty.resolver.AddressResolverGroup;
|
import io.netty.resolver.AddressResolverGroup;
|
||||||
import io.netty.resolver.AbstractAddressResolver;
|
|
||||||
import io.netty.util.concurrent.EventExecutor;
|
import io.netty.util.concurrent.EventExecutor;
|
||||||
import io.netty.util.concurrent.Future;
|
import io.netty.util.concurrent.Future;
|
||||||
import io.netty.util.concurrent.Promise;
|
import io.netty.util.concurrent.Promise;
|
||||||
@ -55,8 +50,14 @@ import java.util.concurrent.BlockingQueue;
|
|||||||
import java.util.concurrent.CountDownLatch;
|
import java.util.concurrent.CountDownLatch;
|
||||||
import java.util.concurrent.LinkedBlockingQueue;
|
import java.util.concurrent.LinkedBlockingQueue;
|
||||||
|
|
||||||
import static org.hamcrest.Matchers.*;
|
import static org.hamcrest.Matchers.sameInstance;
|
||||||
import static org.junit.Assert.*;
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
|
import static org.hamcrest.Matchers.instanceOf;
|
||||||
|
import static org.hamcrest.Matchers.is;
|
||||||
|
import static org.hamcrest.Matchers.not;
|
||||||
|
import static org.hamcrest.Matchers.nullValue;
|
||||||
|
import static org.junit.Assert.assertFalse;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
public class BootstrapTest {
|
public class BootstrapTest {
|
||||||
|
|
||||||
@ -88,18 +89,12 @@ public class BootstrapTest {
|
|||||||
|
|
||||||
// Try to bind from each other.
|
// Try to bind from each other.
|
||||||
for (int i = 0; i < 1024; i ++) {
|
for (int i = 0; i < 1024; i ++) {
|
||||||
bindFutures.add(groupA.next().submit(new Runnable() {
|
bindFutures.add(groupA.next().submit(() -> {
|
||||||
@Override
|
bootstrapB.bind(LocalAddress.ANY);
|
||||||
public void run() {
|
|
||||||
bootstrapB.bind(LocalAddress.ANY);
|
|
||||||
}
|
|
||||||
}));
|
}));
|
||||||
|
|
||||||
bindFutures.add(groupB.next().submit(new Runnable() {
|
bindFutures.add(groupB.next().submit(() -> {
|
||||||
@Override
|
bootstrapA.bind(LocalAddress.ANY);
|
||||||
public void run() {
|
|
||||||
bootstrapA.bind(LocalAddress.ANY);
|
|
||||||
}
|
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -124,18 +119,12 @@ public class BootstrapTest {
|
|||||||
|
|
||||||
// Try to connect from each other.
|
// Try to connect from each other.
|
||||||
for (int i = 0; i < 1024; i ++) {
|
for (int i = 0; i < 1024; i ++) {
|
||||||
bindFutures.add(groupA.next().submit(new Runnable() {
|
bindFutures.add(groupA.next().submit(() -> {
|
||||||
@Override
|
bootstrapB.connect(LocalAddress.ANY);
|
||||||
public void run() {
|
|
||||||
bootstrapB.connect(LocalAddress.ANY);
|
|
||||||
}
|
|
||||||
}));
|
}));
|
||||||
|
|
||||||
bindFutures.add(groupB.next().submit(new Runnable() {
|
bindFutures.add(groupB.next().submit(() -> {
|
||||||
@Override
|
bootstrapA.connect(LocalAddress.ANY);
|
||||||
public void run() {
|
|
||||||
bootstrapA.connect(LocalAddress.ANY);
|
|
||||||
}
|
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -159,12 +148,9 @@ public class BootstrapTest {
|
|||||||
assertFalse(future.isDone());
|
assertFalse(future.isDone());
|
||||||
registerHandler.registerPromise().setSuccess();
|
registerHandler.registerPromise().setSuccess();
|
||||||
final BlockingQueue<Boolean> queue = new LinkedBlockingQueue<>();
|
final BlockingQueue<Boolean> queue = new LinkedBlockingQueue<>();
|
||||||
future.addListener(new ChannelFutureListener() {
|
future.addListener((ChannelFutureListener) future1 -> {
|
||||||
@Override
|
queue.add(future1.channel().eventLoop().inEventLoop(Thread.currentThread()));
|
||||||
public void operationComplete(ChannelFuture future) throws Exception {
|
queue.add(future1.isSuccess());
|
||||||
queue.add(future.channel().eventLoop().inEventLoop(Thread.currentThread()));
|
|
||||||
queue.add(future.isSuccess());
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
assertTrue(queue.take());
|
assertTrue(queue.take());
|
||||||
assertTrue(queue.take());
|
assertTrue(queue.take());
|
||||||
@ -181,10 +167,8 @@ public class BootstrapTest {
|
|||||||
try {
|
try {
|
||||||
ServerBootstrap bootstrap = new ServerBootstrap();
|
ServerBootstrap bootstrap = new ServerBootstrap();
|
||||||
bootstrap.group(group);
|
bootstrap.group(group);
|
||||||
bootstrap.channelFactory(new ServerChannelFactory<ServerChannel>() {
|
bootstrap.channelFactory((eventLoop, childEventLoopGroup) ->
|
||||||
@Override
|
new LocalServerChannel(eventLoop, childEventLoopGroup) {
|
||||||
public ServerChannel newChannel(EventLoop eventLoop, EventLoopGroup childEventLoopGroup) {
|
|
||||||
return new LocalServerChannel(eventLoop, childEventLoopGroup) {
|
|
||||||
@Override
|
@Override
|
||||||
public ChannelFuture bind(SocketAddress localAddress) {
|
public ChannelFuture bind(SocketAddress localAddress) {
|
||||||
// Close the Channel to emulate what NIO and others impl do on bind failure
|
// Close the Channel to emulate what NIO and others impl do on bind failure
|
||||||
@ -200,9 +184,7 @@ public class BootstrapTest {
|
|||||||
close();
|
close();
|
||||||
return promise.setFailure(new SocketException());
|
return promise.setFailure(new SocketException());
|
||||||
}
|
}
|
||||||
};
|
});
|
||||||
}
|
|
||||||
});
|
|
||||||
bootstrap.childHandler(new DummyHandler());
|
bootstrap.childHandler(new DummyHandler());
|
||||||
bootstrap.handler(registerHandler);
|
bootstrap.handler(registerHandler);
|
||||||
bootstrap.localAddress(new LocalAddress("1"));
|
bootstrap.localAddress(new LocalAddress("1"));
|
||||||
@ -210,12 +192,9 @@ public class BootstrapTest {
|
|||||||
assertFalse(future.isDone());
|
assertFalse(future.isDone());
|
||||||
registerHandler.registerPromise().setSuccess();
|
registerHandler.registerPromise().setSuccess();
|
||||||
final BlockingQueue<Boolean> queue = new LinkedBlockingQueue<>();
|
final BlockingQueue<Boolean> queue = new LinkedBlockingQueue<>();
|
||||||
future.addListener(new ChannelFutureListener() {
|
future.addListener((ChannelFutureListener) future1 -> {
|
||||||
@Override
|
queue.add(future1.channel().eventLoop().inEventLoop(Thread.currentThread()));
|
||||||
public void operationComplete(ChannelFuture future) throws Exception {
|
queue.add(future1.isSuccess());
|
||||||
queue.add(future.channel().eventLoop().inEventLoop(Thread.currentThread()));
|
|
||||||
queue.add(future.isSuccess());
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
assertTrue(queue.take());
|
assertTrue(queue.take());
|
||||||
assertFalse(queue.take());
|
assertFalse(queue.take());
|
||||||
@ -291,12 +270,9 @@ public class BootstrapTest {
|
|||||||
final Bootstrap bootstrap = new Bootstrap()
|
final Bootstrap bootstrap = new Bootstrap()
|
||||||
.handler(dummyHandler)
|
.handler(dummyHandler)
|
||||||
.group(groupA)
|
.group(groupA)
|
||||||
.channelFactory(new ChannelFactory<Channel>() {
|
.channelFactory(eventLoop -> {
|
||||||
@Override
|
throw exception;
|
||||||
public Channel newChannel(EventLoop eventLoop) {
|
});
|
||||||
throw exception;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
ChannelFuture connectFuture = bootstrap.connect(LocalAddress.ANY);
|
ChannelFuture connectFuture = bootstrap.connect(LocalAddress.ANY);
|
||||||
|
|
||||||
@ -316,12 +292,9 @@ public class BootstrapTest {
|
|||||||
registerPromise = promise;
|
registerPromise = promise;
|
||||||
latch.countDown();
|
latch.countDown();
|
||||||
ChannelPromise newPromise = ctx.newPromise();
|
ChannelPromise newPromise = ctx.newPromise();
|
||||||
newPromise.addListener(new ChannelFutureListener() {
|
newPromise.addListener((ChannelFutureListener) future -> {
|
||||||
@Override
|
if (!future.isSuccess()) {
|
||||||
public void operationComplete(ChannelFuture future) throws Exception {
|
registerPromise.tryFailure(future.cause());
|
||||||
if (!future.isSuccess()) {
|
|
||||||
registerPromise.tryFailure(future.cause());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
super.register(ctx, newPromise);
|
super.register(ctx, newPromise);
|
||||||
@ -356,14 +329,11 @@ public class BootstrapTest {
|
|||||||
@Override
|
@Override
|
||||||
protected void doResolve(
|
protected void doResolve(
|
||||||
final SocketAddress unresolvedAddress, final Promise<SocketAddress> promise) {
|
final SocketAddress unresolvedAddress, final Promise<SocketAddress> promise) {
|
||||||
executor().execute(new Runnable() {
|
executor().execute(() -> {
|
||||||
@Override
|
if (success) {
|
||||||
public void run() {
|
promise.setSuccess(unresolvedAddress);
|
||||||
if (success) {
|
} else {
|
||||||
promise.setSuccess(unresolvedAddress);
|
promise.setFailure(new UnknownHostException(unresolvedAddress.toString()));
|
||||||
} else {
|
|
||||||
promise.setFailure(new UnknownHostException(unresolvedAddress.toString()));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -372,14 +342,11 @@ public class BootstrapTest {
|
|||||||
protected void doResolveAll(
|
protected void doResolveAll(
|
||||||
final SocketAddress unresolvedAddress, final Promise<List<SocketAddress>> promise)
|
final SocketAddress unresolvedAddress, final Promise<List<SocketAddress>> promise)
|
||||||
throws Exception {
|
throws Exception {
|
||||||
executor().execute(new Runnable() {
|
executor().execute(() -> {
|
||||||
@Override
|
if (success) {
|
||||||
public void run() {
|
promise.setSuccess(Collections.singletonList(unresolvedAddress));
|
||||||
if (success) {
|
} else {
|
||||||
promise.setSuccess(Collections.singletonList(unresolvedAddress));
|
promise.setFailure(new UnknownHostException(unresolvedAddress.toString()));
|
||||||
} else {
|
|
||||||
promise.setFailure(new UnknownHostException(unresolvedAddress.toString()));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -51,12 +51,9 @@ public class AbstractChannelTest {
|
|||||||
when(eventLoop.inEventLoop()).thenReturn(true);
|
when(eventLoop.inEventLoop()).thenReturn(true);
|
||||||
when(eventLoop.unsafe()).thenReturn(mock(EventLoop.Unsafe.class));
|
when(eventLoop.unsafe()).thenReturn(mock(EventLoop.Unsafe.class));
|
||||||
|
|
||||||
doAnswer(new Answer() {
|
doAnswer(invocationOnMock -> {
|
||||||
@Override
|
((Runnable) invocationOnMock.getArgument(0)).run();
|
||||||
public Object answer(InvocationOnMock invocationOnMock) throws Throwable {
|
return null;
|
||||||
((Runnable) invocationOnMock.getArgument(0)).run();
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}).when(eventLoop).execute(any(Runnable.class));
|
}).when(eventLoop).execute(any(Runnable.class));
|
||||||
|
|
||||||
final TestChannel channel = new TestChannel(eventLoop);
|
final TestChannel channel = new TestChannel(eventLoop);
|
||||||
|
@ -146,11 +146,8 @@ public class ChannelInitializerTest {
|
|||||||
try {
|
try {
|
||||||
// Execute some task on the EventLoop and wait until its done to be sure all handlers are added to the
|
// Execute some task on the EventLoop and wait until its done to be sure all handlers are added to the
|
||||||
// pipeline.
|
// pipeline.
|
||||||
channel.eventLoop().submit(new Runnable() {
|
channel.eventLoop().submit(() -> {
|
||||||
@Override
|
// NOOP
|
||||||
public void run() {
|
|
||||||
// NOOP
|
|
||||||
}
|
|
||||||
}).syncUninterruptibly();
|
}).syncUninterruptibly();
|
||||||
Iterator<Map.Entry<String, ChannelHandler>> handlers = channel.pipeline().iterator();
|
Iterator<Map.Entry<String, ChannelHandler>> handlers = channel.pipeline().iterator();
|
||||||
assertSame(handler1, handlers.next().getValue());
|
assertSame(handler1, handlers.next().getValue());
|
||||||
@ -186,11 +183,8 @@ public class ChannelInitializerTest {
|
|||||||
try {
|
try {
|
||||||
// Execute some task on the EventLoop and wait until its done to be sure all handlers are added to the
|
// Execute some task on the EventLoop and wait until its done to be sure all handlers are added to the
|
||||||
// pipeline.
|
// pipeline.
|
||||||
channel.eventLoop().submit(new Runnable() {
|
channel.eventLoop().submit(() -> {
|
||||||
@Override
|
// NOOP
|
||||||
public void run() {
|
|
||||||
// NOOP
|
|
||||||
}
|
|
||||||
}).syncUninterruptibly();
|
}).syncUninterruptibly();
|
||||||
assertEquals(1, initChannelCalled.get());
|
assertEquals(1, initChannelCalled.get());
|
||||||
assertEquals(2, registeredCalled.get());
|
assertEquals(2, registeredCalled.get());
|
||||||
|
@ -424,25 +424,19 @@ public class ChannelOutboundBufferTest {
|
|||||||
|
|
||||||
final CountDownLatch executeLatch = new CountDownLatch(1);
|
final CountDownLatch executeLatch = new CountDownLatch(1);
|
||||||
final CountDownLatch runLatch = new CountDownLatch(1);
|
final CountDownLatch runLatch = new CountDownLatch(1);
|
||||||
executor.execute(new Runnable() {
|
executor.execute(() -> {
|
||||||
@Override
|
try {
|
||||||
public void run() {
|
runLatch.countDown();
|
||||||
try {
|
executeLatch.await();
|
||||||
runLatch.countDown();
|
} catch (InterruptedException e) {
|
||||||
executeLatch.await();
|
Thread.currentThread().interrupt();
|
||||||
} catch (InterruptedException e) {
|
|
||||||
Thread.currentThread().interrupt();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
runLatch.await();
|
runLatch.await();
|
||||||
|
|
||||||
executor.execute(new Runnable() {
|
executor.execute(() -> {
|
||||||
@Override
|
// Will not be executed but ensure the pending count is 1.
|
||||||
public void run() {
|
|
||||||
// Will not be executed but ensure the pending count is 1.
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
assertEquals(1, executor.pendingTasks());
|
assertEquals(1, executor.pendingTasks());
|
||||||
|
@ -53,12 +53,9 @@ public class CoalescingBufferQueueTest {
|
|||||||
channel = new EmbeddedChannel();
|
channel = new EmbeddedChannel();
|
||||||
writeQueue = new CoalescingBufferQueue(channel, 16, true);
|
writeQueue = new CoalescingBufferQueue(channel, 16, true);
|
||||||
catPromise = newPromise();
|
catPromise = newPromise();
|
||||||
mouseListener = new ChannelFutureListener() {
|
mouseListener = future -> {
|
||||||
@Override
|
mouseDone = true;
|
||||||
public void operationComplete(ChannelFuture future) throws Exception {
|
mouseSuccess = future.isSuccess();
|
||||||
mouseDone = true;
|
|
||||||
mouseSuccess = future.isSuccess();
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
emptyPromise = newPromise();
|
emptyPromise = newPromise();
|
||||||
voidPromise = channel.voidPromise();
|
voidPromise = channel.voidPromise();
|
||||||
|
@ -368,17 +368,14 @@ public class DefaultChannelPipelineTest {
|
|||||||
|
|
||||||
// Add handler.
|
// Add handler.
|
||||||
p.addFirst(handler.name, handler);
|
p.addFirst(handler.name, handler);
|
||||||
self.eventLoop().execute(new Runnable() {
|
self.eventLoop().execute(() -> {
|
||||||
@Override
|
// Validate handler life-cycle methods called.
|
||||||
public void run() {
|
handler.validate(true, false);
|
||||||
// Validate handler life-cycle methods called.
|
|
||||||
handler.validate(true, false);
|
|
||||||
|
|
||||||
// Store handler into the list.
|
// Store handler into the list.
|
||||||
handlers.add(handler);
|
handlers.add(handler);
|
||||||
|
|
||||||
addLatch.countDown();
|
addLatch.countDown();
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
addLatch.await();
|
addLatch.await();
|
||||||
@ -391,13 +388,10 @@ public class DefaultChannelPipelineTest {
|
|||||||
for (final LifeCycleAwareTestHandler handler : handlers) {
|
for (final LifeCycleAwareTestHandler handler : handlers) {
|
||||||
assertSame(handler, p.remove(handler.name));
|
assertSame(handler, p.remove(handler.name));
|
||||||
|
|
||||||
self.eventLoop().execute(new Runnable() {
|
self.eventLoop().execute(() -> {
|
||||||
@Override
|
// Validate handler life-cycle methods called.
|
||||||
public void run() {
|
handler.validate(true, true);
|
||||||
// Validate handler life-cycle methods called.
|
removeLatch.countDown();
|
||||||
handler.validate(true, true);
|
|
||||||
removeLatch.countDown();
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
removeLatch.await();
|
removeLatch.await();
|
||||||
@ -410,17 +404,14 @@ public class DefaultChannelPipelineTest {
|
|||||||
|
|
||||||
setUp(handler1, handler2);
|
setUp(handler1, handler2);
|
||||||
|
|
||||||
self.eventLoop().submit(new Runnable() {
|
self.eventLoop().submit(() -> {
|
||||||
@Override
|
ChannelPipeline p = self.pipeline();
|
||||||
public void run() {
|
handler1.inboundBuffer.add(8);
|
||||||
ChannelPipeline p = self.pipeline();
|
assertEquals(8, handler1.inboundBuffer.peek());
|
||||||
handler1.inboundBuffer.add(8);
|
assertTrue(handler2.inboundBuffer.isEmpty());
|
||||||
assertEquals(8, handler1.inboundBuffer.peek());
|
p.remove(handler1);
|
||||||
assertTrue(handler2.inboundBuffer.isEmpty());
|
assertEquals(1, handler2.inboundBuffer.size());
|
||||||
p.remove(handler1);
|
assertEquals(8, handler2.inboundBuffer.peek());
|
||||||
assertEquals(1, handler2.inboundBuffer.size());
|
|
||||||
assertEquals(8, handler2.inboundBuffer.peek());
|
|
||||||
}
|
|
||||||
}).sync();
|
}).sync();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -431,17 +422,14 @@ public class DefaultChannelPipelineTest {
|
|||||||
|
|
||||||
setUp(handler1, handler2);
|
setUp(handler1, handler2);
|
||||||
|
|
||||||
self.eventLoop().submit(new Runnable() {
|
self.eventLoop().submit(() -> {
|
||||||
@Override
|
ChannelPipeline p = self.pipeline();
|
||||||
public void run() {
|
handler2.outboundBuffer.add(8);
|
||||||
ChannelPipeline p = self.pipeline();
|
assertEquals(8, handler2.outboundBuffer.peek());
|
||||||
handler2.outboundBuffer.add(8);
|
assertTrue(handler1.outboundBuffer.isEmpty());
|
||||||
assertEquals(8, handler2.outboundBuffer.peek());
|
p.remove(handler2);
|
||||||
assertTrue(handler1.outboundBuffer.isEmpty());
|
assertEquals(1, handler1.outboundBuffer.size());
|
||||||
p.remove(handler2);
|
assertEquals(8, handler1.outboundBuffer.peek());
|
||||||
assertEquals(1, handler1.outboundBuffer.size());
|
|
||||||
assertEquals(8, handler1.outboundBuffer.peek());
|
|
||||||
}
|
|
||||||
}).sync();
|
}).sync();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -452,16 +440,13 @@ public class DefaultChannelPipelineTest {
|
|||||||
|
|
||||||
setUp(handler1);
|
setUp(handler1);
|
||||||
|
|
||||||
self.eventLoop().submit(new Runnable() {
|
self.eventLoop().submit(() -> {
|
||||||
@Override
|
ChannelPipeline p = self.pipeline();
|
||||||
public void run() {
|
handler1.outboundBuffer.add(8);
|
||||||
ChannelPipeline p = self.pipeline();
|
assertEquals(8, handler1.outboundBuffer.peek());
|
||||||
handler1.outboundBuffer.add(8);
|
assertTrue(handler2.outboundBuffer.isEmpty());
|
||||||
assertEquals(8, handler1.outboundBuffer.peek());
|
p.replace(handler1, "handler2", handler2);
|
||||||
assertTrue(handler2.outboundBuffer.isEmpty());
|
assertEquals(8, handler2.outboundBuffer.peek());
|
||||||
p.replace(handler1, "handler2", handler2);
|
|
||||||
assertEquals(8, handler2.outboundBuffer.peek());
|
|
||||||
}
|
|
||||||
}).sync();
|
}).sync();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -472,22 +457,19 @@ public class DefaultChannelPipelineTest {
|
|||||||
|
|
||||||
setUp(handler1);
|
setUp(handler1);
|
||||||
|
|
||||||
self.eventLoop().submit(new Runnable() {
|
self.eventLoop().submit(() -> {
|
||||||
@Override
|
ChannelPipeline p = self.pipeline();
|
||||||
public void run() {
|
handler1.inboundBuffer.add(8);
|
||||||
ChannelPipeline p = self.pipeline();
|
handler1.outboundBuffer.add(8);
|
||||||
handler1.inboundBuffer.add(8);
|
|
||||||
handler1.outboundBuffer.add(8);
|
|
||||||
|
|
||||||
assertEquals(8, handler1.inboundBuffer.peek());
|
assertEquals(8, handler1.inboundBuffer.peek());
|
||||||
assertEquals(8, handler1.outboundBuffer.peek());
|
assertEquals(8, handler1.outboundBuffer.peek());
|
||||||
assertTrue(handler2.inboundBuffer.isEmpty());
|
assertTrue(handler2.inboundBuffer.isEmpty());
|
||||||
assertTrue(handler2.outboundBuffer.isEmpty());
|
assertTrue(handler2.outboundBuffer.isEmpty());
|
||||||
|
|
||||||
p.replace(handler1, "handler2", handler2);
|
p.replace(handler1, "handler2", handler2);
|
||||||
assertEquals(8, handler2.outboundBuffer.peek());
|
assertEquals(8, handler2.outboundBuffer.peek());
|
||||||
assertEquals(8, handler2.inboundBuffer.peek());
|
assertEquals(8, handler2.inboundBuffer.peek());
|
||||||
}
|
|
||||||
}).sync();
|
}).sync();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -499,23 +481,20 @@ public class DefaultChannelPipelineTest {
|
|||||||
|
|
||||||
setUp(handler1, handler2, handler3);
|
setUp(handler1, handler2, handler3);
|
||||||
|
|
||||||
self.eventLoop().submit(new Runnable() {
|
self.eventLoop().submit(() -> {
|
||||||
@Override
|
ChannelPipeline p = self.pipeline();
|
||||||
public void run() {
|
handler2.inboundBuffer.add(8);
|
||||||
ChannelPipeline p = self.pipeline();
|
handler2.outboundBuffer.add(8);
|
||||||
handler2.inboundBuffer.add(8);
|
|
||||||
handler2.outboundBuffer.add(8);
|
|
||||||
|
|
||||||
assertEquals(8, handler2.inboundBuffer.peek());
|
assertEquals(8, handler2.inboundBuffer.peek());
|
||||||
assertEquals(8, handler2.outboundBuffer.peek());
|
assertEquals(8, handler2.outboundBuffer.peek());
|
||||||
|
|
||||||
assertEquals(0, handler1.outboundBuffer.size());
|
assertEquals(0, handler1.outboundBuffer.size());
|
||||||
assertEquals(0, handler3.inboundBuffer.size());
|
assertEquals(0, handler3.inboundBuffer.size());
|
||||||
|
|
||||||
p.remove(handler2);
|
p.remove(handler2);
|
||||||
assertEquals(8, handler3.inboundBuffer.peek());
|
assertEquals(8, handler3.inboundBuffer.peek());
|
||||||
assertEquals(8, handler1.outboundBuffer.peek());
|
assertEquals(8, handler1.outboundBuffer.peek());
|
||||||
}
|
|
||||||
}).sync();
|
}).sync();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -870,12 +849,7 @@ public class DefaultChannelPipelineTest {
|
|||||||
@Override
|
@Override
|
||||||
public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
|
public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
|
||||||
// Execute this later so we are sure the exception is handled first.
|
// Execute this later so we are sure the exception is handled first.
|
||||||
ctx.executor().execute(new Runnable() {
|
ctx.executor().execute(latch::countDown);
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
latch.countDown();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
throw exceptionRemoved;
|
throw exceptionRemoved;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -986,34 +960,31 @@ public class DefaultChannelPipelineTest {
|
|||||||
try {
|
try {
|
||||||
final Object event = new Object();
|
final Object event = new Object();
|
||||||
final Promise<Object> promise = ImmediateEventExecutor.INSTANCE.newPromise();
|
final Promise<Object> promise = ImmediateEventExecutor.INSTANCE.newPromise();
|
||||||
pipeline1.channel().register().addListener(new ChannelFutureListener() {
|
pipeline1.channel().register().addListener((ChannelFutureListener) future -> {
|
||||||
@Override
|
ChannelPipeline pipeline = future.channel().pipeline();
|
||||||
public void operationComplete(ChannelFuture future) throws Exception {
|
final AtomicBoolean handlerAddedCalled = new AtomicBoolean();
|
||||||
ChannelPipeline pipeline = future.channel().pipeline();
|
pipeline.addLast(new ChannelInboundHandlerAdapter() {
|
||||||
final AtomicBoolean handlerAddedCalled = new AtomicBoolean();
|
@Override
|
||||||
pipeline.addLast(new ChannelInboundHandlerAdapter() {
|
public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
|
||||||
@Override
|
handlerAddedCalled.set(true);
|
||||||
public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
|
|
||||||
handlerAddedCalled.set(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
|
|
||||||
promise.setSuccess(event);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
|
|
||||||
promise.setFailure(cause);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
if (!handlerAddedCalled.get()) {
|
|
||||||
promise.setFailure(new AssertionError("handlerAdded(...) should have been called"));
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
// This event must be captured by the added handler.
|
|
||||||
pipeline.fireUserEventTriggered(event);
|
@Override
|
||||||
|
public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
|
||||||
|
promise.setSuccess(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
|
||||||
|
promise.setFailure(cause);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (!handlerAddedCalled.get()) {
|
||||||
|
promise.setFailure(new AssertionError("handlerAdded(...) should have been called"));
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
// This event must be captured by the added handler.
|
||||||
|
pipeline.fireUserEventTriggered(event);
|
||||||
});
|
});
|
||||||
assertSame(event, promise.syncUninterruptibly().getNow());
|
assertSame(event, promise.syncUninterruptibly().getNow());
|
||||||
} finally {
|
} finally {
|
||||||
@ -1184,11 +1155,8 @@ public class DefaultChannelPipelineTest {
|
|||||||
pipeline.channel().closeFuture().syncUninterruptibly();
|
pipeline.channel().closeFuture().syncUninterruptibly();
|
||||||
|
|
||||||
// Schedule something on the EventLoop to ensure all other scheduled tasks had a chance to complete.
|
// Schedule something on the EventLoop to ensure all other scheduled tasks had a chance to complete.
|
||||||
pipeline.channel().eventLoop().submit(new Runnable() {
|
pipeline.channel().eventLoop().submit(() -> {
|
||||||
@Override
|
// NOOP
|
||||||
public void run() {
|
|
||||||
// NOOP
|
|
||||||
}
|
|
||||||
}).syncUninterruptibly();
|
}).syncUninterruptibly();
|
||||||
Error error = errorRef.get();
|
Error error = errorRef.get();
|
||||||
if (error != null) {
|
if (error != null) {
|
||||||
@ -1646,33 +1614,30 @@ public class DefaultChannelPipelineTest {
|
|||||||
final Object writeObject = new Object();
|
final Object writeObject = new Object();
|
||||||
final CountDownLatch doneLatch = new CountDownLatch(1);
|
final CountDownLatch doneLatch = new CountDownLatch(1);
|
||||||
|
|
||||||
Runnable r = new Runnable() {
|
Runnable r = () -> {
|
||||||
@Override
|
pipeline.addLast(new ChannelInboundHandlerAdapter() {
|
||||||
public void run() {
|
@Override
|
||||||
pipeline.addLast(new ChannelInboundHandlerAdapter() {
|
public void userEventTriggered(ChannelHandlerContext ctx, Object evt) {
|
||||||
@Override
|
if (evt == userEvent) {
|
||||||
public void userEventTriggered(ChannelHandlerContext ctx, Object evt) {
|
ctx.write(writeObject);
|
||||||
if (evt == userEvent) {
|
|
||||||
ctx.write(writeObject);
|
|
||||||
}
|
|
||||||
ctx.fireUserEventTriggered(evt);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
pipeline.addFirst(new ChannelDuplexHandler() {
|
|
||||||
@Override
|
|
||||||
public void handlerAdded(ChannelHandlerContext ctx) {
|
|
||||||
ctx.fireUserEventTriggered(userEvent);
|
|
||||||
}
|
}
|
||||||
|
ctx.fireUserEventTriggered(evt);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
pipeline.addFirst(new ChannelDuplexHandler() {
|
||||||
|
@Override
|
||||||
|
public void handlerAdded(ChannelHandlerContext ctx) {
|
||||||
|
ctx.fireUserEventTriggered(userEvent);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) {
|
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) {
|
||||||
if (msg == writeObject) {
|
if (msg == writeObject) {
|
||||||
doneLatch.countDown();
|
doneLatch.countDown();
|
||||||
}
|
|
||||||
ctx.write(msg, promise);
|
|
||||||
}
|
}
|
||||||
});
|
ctx.write(msg, promise);
|
||||||
}
|
}
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
if (executeInEventLoop) {
|
if (executeInEventLoop) {
|
||||||
|
@ -40,12 +40,7 @@ public class PendingWriteQueueTest {
|
|||||||
assertFalse("Should not be writable anymore", ctx.channel().isWritable());
|
assertFalse("Should not be writable anymore", ctx.channel().isWritable());
|
||||||
|
|
||||||
ChannelFuture future = queue.removeAndWrite();
|
ChannelFuture future = queue.removeAndWrite();
|
||||||
future.addListener(new ChannelFutureListener() {
|
future.addListener((ChannelFutureListener) future1 -> assertQueueEmpty(queue));
|
||||||
@Override
|
|
||||||
public void operationComplete(ChannelFuture future) throws Exception {
|
|
||||||
assertQueueEmpty(queue);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
super.flush(ctx);
|
super.flush(ctx);
|
||||||
}
|
}
|
||||||
}, 1);
|
}, 1);
|
||||||
@ -59,12 +54,7 @@ public class PendingWriteQueueTest {
|
|||||||
assertFalse("Should not be writable anymore", ctx.channel().isWritable());
|
assertFalse("Should not be writable anymore", ctx.channel().isWritable());
|
||||||
|
|
||||||
ChannelFuture future = queue.removeAndWriteAll();
|
ChannelFuture future = queue.removeAndWriteAll();
|
||||||
future.addListener(new ChannelFutureListener() {
|
future.addListener((ChannelFutureListener) future1 -> assertQueueEmpty(queue));
|
||||||
@Override
|
|
||||||
public void operationComplete(ChannelFuture future) throws Exception {
|
|
||||||
assertQueueEmpty(queue);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
super.flush(ctx);
|
super.flush(ctx);
|
||||||
}
|
}
|
||||||
}, 3);
|
}, 3);
|
||||||
@ -209,12 +199,7 @@ public class PendingWriteQueueTest {
|
|||||||
final PendingWriteQueue queue = new PendingWriteQueue(channel.pipeline().firstContext());
|
final PendingWriteQueue queue = new PendingWriteQueue(channel.pipeline().firstContext());
|
||||||
|
|
||||||
ChannelPromise promise = channel.newPromise();
|
ChannelPromise promise = channel.newPromise();
|
||||||
promise.addListener(new ChannelFutureListener() {
|
promise.addListener((ChannelFutureListener) future -> queue.removeAndFailAll(new IllegalStateException()));
|
||||||
@Override
|
|
||||||
public void operationComplete(ChannelFuture future) throws Exception {
|
|
||||||
queue.removeAndFailAll(new IllegalStateException());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
queue.add(1L, promise);
|
queue.add(1L, promise);
|
||||||
|
|
||||||
ChannelPromise promise2 = channel.newPromise();
|
ChannelPromise promise2 = channel.newPromise();
|
||||||
@ -241,12 +226,7 @@ public class PendingWriteQueueTest {
|
|||||||
|
|
||||||
ChannelPromise promise = channel.newPromise();
|
ChannelPromise promise = channel.newPromise();
|
||||||
final ChannelPromise promise3 = channel.newPromise();
|
final ChannelPromise promise3 = channel.newPromise();
|
||||||
promise.addListener(new ChannelFutureListener() {
|
promise.addListener((ChannelFutureListener) future -> queue.add(3L, promise3));
|
||||||
@Override
|
|
||||||
public void operationComplete(ChannelFuture future) {
|
|
||||||
queue.add(3L, promise3);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
queue.add(1L, promise);
|
queue.add(1L, promise);
|
||||||
ChannelPromise promise2 = channel.newPromise();
|
ChannelPromise promise2 = channel.newPromise();
|
||||||
queue.add(2L, promise2);
|
queue.add(2L, promise2);
|
||||||
@ -296,28 +276,15 @@ public class PendingWriteQueueTest {
|
|||||||
|
|
||||||
ChannelPromise promise = channel.newPromise();
|
ChannelPromise promise = channel.newPromise();
|
||||||
final ChannelPromise promise3 = channel.newPromise();
|
final ChannelPromise promise3 = channel.newPromise();
|
||||||
promise3.addListener(new ChannelFutureListener() {
|
promise3.addListener((ChannelFutureListener) future -> failOrder.add(3));
|
||||||
@Override
|
promise.addListener((ChannelFutureListener) future -> {
|
||||||
public void operationComplete(ChannelFuture future) throws Exception {
|
failOrder.add(1);
|
||||||
failOrder.add(3);
|
queue.add(3L, promise3);
|
||||||
}
|
|
||||||
});
|
|
||||||
promise.addListener(new ChannelFutureListener() {
|
|
||||||
@Override
|
|
||||||
public void operationComplete(ChannelFuture future) throws Exception {
|
|
||||||
failOrder.add(1);
|
|
||||||
queue.add(3L, promise3);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
queue.add(1L, promise);
|
queue.add(1L, promise);
|
||||||
|
|
||||||
ChannelPromise promise2 = channel.newPromise();
|
ChannelPromise promise2 = channel.newPromise();
|
||||||
promise2.addListener(new ChannelFutureListener() {
|
promise2.addListener((ChannelFutureListener) future -> failOrder.add(2));
|
||||||
@Override
|
|
||||||
public void operationComplete(ChannelFuture future) throws Exception {
|
|
||||||
failOrder.add(2);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
queue.add(2L, promise2);
|
queue.add(2L, promise2);
|
||||||
queue.removeAndFailAll(new Exception());
|
queue.removeAndFailAll(new Exception());
|
||||||
assertTrue(promise.isDone());
|
assertTrue(promise.isDone());
|
||||||
@ -338,12 +305,7 @@ public class PendingWriteQueueTest {
|
|||||||
final PendingWriteQueue queue = new PendingWriteQueue(channel.pipeline().firstContext());
|
final PendingWriteQueue queue = new PendingWriteQueue(channel.pipeline().firstContext());
|
||||||
|
|
||||||
ChannelPromise promise = channel.newPromise();
|
ChannelPromise promise = channel.newPromise();
|
||||||
promise.addListener(new ChannelFutureListener() {
|
promise.addListener((ChannelFutureListener) future -> queue.removeAndWriteAll());
|
||||||
@Override
|
|
||||||
public void operationComplete(ChannelFuture future) throws Exception {
|
|
||||||
queue.removeAndWriteAll();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
queue.add(1L, promise);
|
queue.add(1L, promise);
|
||||||
|
|
||||||
ChannelPromise promise2 = channel.newPromise();
|
ChannelPromise promise2 = channel.newPromise();
|
||||||
|
@ -226,12 +226,7 @@ public class ReentrantChannelTest extends BaseChannelTest {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void write(final ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
|
public void write(final ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
|
||||||
promise.addListener(new GenericFutureListener<Future<? super Void>>() {
|
promise.addListener(future -> ctx.channel().close());
|
||||||
@Override
|
|
||||||
public void operationComplete(Future<? super Void> future) throws Exception {
|
|
||||||
ctx.channel().close();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
super.write(ctx, msg, promise);
|
super.write(ctx, msg, promise);
|
||||||
ctx.channel().flush();
|
ctx.channel().flush();
|
||||||
}
|
}
|
||||||
|
@ -46,10 +46,7 @@ import static org.junit.Assert.*;
|
|||||||
|
|
||||||
public class SingleThreadEventLoopTest {
|
public class SingleThreadEventLoopTest {
|
||||||
|
|
||||||
private static final Runnable NOOP = new Runnable() {
|
private static final Runnable NOOP = () -> { };
|
||||||
@Override
|
|
||||||
public void run() { }
|
|
||||||
};
|
|
||||||
|
|
||||||
private SingleThreadEventLoopA loopA;
|
private SingleThreadEventLoopA loopA;
|
||||||
private SingleThreadEventLoopB loopB;
|
private SingleThreadEventLoopB loopB;
|
||||||
@ -98,12 +95,7 @@ public class SingleThreadEventLoopTest {
|
|||||||
@SuppressWarnings("deprecation")
|
@SuppressWarnings("deprecation")
|
||||||
public void shutdownAfterStart() throws Exception {
|
public void shutdownAfterStart() throws Exception {
|
||||||
final CountDownLatch latch = new CountDownLatch(1);
|
final CountDownLatch latch = new CountDownLatch(1);
|
||||||
loopA.execute(new Runnable() {
|
loopA.execute(latch::countDown);
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
latch.countDown();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Wait for the event loop thread to start.
|
// Wait for the event loop thread to start.
|
||||||
latch.await();
|
latch.await();
|
||||||
@ -142,12 +134,7 @@ public class SingleThreadEventLoopTest {
|
|||||||
private static void testScheduleTask(EventLoop loopA) throws InterruptedException, ExecutionException {
|
private static void testScheduleTask(EventLoop loopA) throws InterruptedException, ExecutionException {
|
||||||
long startTime = System.nanoTime();
|
long startTime = System.nanoTime();
|
||||||
final AtomicLong endTime = new AtomicLong();
|
final AtomicLong endTime = new AtomicLong();
|
||||||
loopA.schedule(new Runnable() {
|
loopA.schedule(() -> endTime.set(System.nanoTime()), 500, TimeUnit.MILLISECONDS).get();
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
endTime.set(System.nanoTime());
|
|
||||||
}
|
|
||||||
}, 500, TimeUnit.MILLISECONDS).get();
|
|
||||||
assertThat(endTime.get() - startTime,
|
assertThat(endTime.get() - startTime,
|
||||||
is(greaterThanOrEqualTo(TimeUnit.MILLISECONDS.toNanos(500))));
|
is(greaterThanOrEqualTo(TimeUnit.MILLISECONDS.toNanos(500))));
|
||||||
}
|
}
|
||||||
@ -166,17 +153,14 @@ public class SingleThreadEventLoopTest {
|
|||||||
final Queue<Long> timestamps = new LinkedBlockingQueue<>();
|
final Queue<Long> timestamps = new LinkedBlockingQueue<>();
|
||||||
final int expectedTimeStamps = 5;
|
final int expectedTimeStamps = 5;
|
||||||
final CountDownLatch allTimeStampsLatch = new CountDownLatch(expectedTimeStamps);
|
final CountDownLatch allTimeStampsLatch = new CountDownLatch(expectedTimeStamps);
|
||||||
ScheduledFuture<?> f = loopA.scheduleAtFixedRate(new Runnable() {
|
ScheduledFuture<?> f = loopA.scheduleAtFixedRate(() -> {
|
||||||
@Override
|
timestamps.add(System.nanoTime());
|
||||||
public void run() {
|
try {
|
||||||
timestamps.add(System.nanoTime());
|
Thread.sleep(50);
|
||||||
try {
|
} catch (InterruptedException e) {
|
||||||
Thread.sleep(50);
|
// Ignore
|
||||||
} catch (InterruptedException e) {
|
|
||||||
// Ignore
|
|
||||||
}
|
|
||||||
allTimeStampsLatch.countDown();
|
|
||||||
}
|
}
|
||||||
|
allTimeStampsLatch.countDown();
|
||||||
}, 100, 100, TimeUnit.MILLISECONDS);
|
}, 100, 100, TimeUnit.MILLISECONDS);
|
||||||
allTimeStampsLatch.await();
|
allTimeStampsLatch.await();
|
||||||
assertTrue(f.cancel(true));
|
assertTrue(f.cancel(true));
|
||||||
@ -214,20 +198,17 @@ public class SingleThreadEventLoopTest {
|
|||||||
final Queue<Long> timestamps = new LinkedBlockingQueue<>();
|
final Queue<Long> timestamps = new LinkedBlockingQueue<>();
|
||||||
final int expectedTimeStamps = 5;
|
final int expectedTimeStamps = 5;
|
||||||
final CountDownLatch allTimeStampsLatch = new CountDownLatch(expectedTimeStamps);
|
final CountDownLatch allTimeStampsLatch = new CountDownLatch(expectedTimeStamps);
|
||||||
ScheduledFuture<?> f = loopA.scheduleAtFixedRate(new Runnable() {
|
ScheduledFuture<?> f = loopA.scheduleAtFixedRate(() -> {
|
||||||
@Override
|
boolean empty = timestamps.isEmpty();
|
||||||
public void run() {
|
timestamps.add(System.nanoTime());
|
||||||
boolean empty = timestamps.isEmpty();
|
if (empty) {
|
||||||
timestamps.add(System.nanoTime());
|
try {
|
||||||
if (empty) {
|
Thread.sleep(401);
|
||||||
try {
|
} catch (InterruptedException e) {
|
||||||
Thread.sleep(401);
|
// Ignore
|
||||||
} catch (InterruptedException e) {
|
|
||||||
// Ignore
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
allTimeStampsLatch.countDown();
|
|
||||||
}
|
}
|
||||||
|
allTimeStampsLatch.countDown();
|
||||||
}, 100, 100, TimeUnit.MILLISECONDS);
|
}, 100, 100, TimeUnit.MILLISECONDS);
|
||||||
allTimeStampsLatch.await();
|
allTimeStampsLatch.await();
|
||||||
assertTrue(f.cancel(true));
|
assertTrue(f.cancel(true));
|
||||||
@ -268,17 +249,14 @@ public class SingleThreadEventLoopTest {
|
|||||||
final Queue<Long> timestamps = new LinkedBlockingQueue<>();
|
final Queue<Long> timestamps = new LinkedBlockingQueue<>();
|
||||||
final int expectedTimeStamps = 3;
|
final int expectedTimeStamps = 3;
|
||||||
final CountDownLatch allTimeStampsLatch = new CountDownLatch(expectedTimeStamps);
|
final CountDownLatch allTimeStampsLatch = new CountDownLatch(expectedTimeStamps);
|
||||||
ScheduledFuture<?> f = loopA.scheduleWithFixedDelay(new Runnable() {
|
ScheduledFuture<?> f = loopA.scheduleWithFixedDelay(() -> {
|
||||||
@Override
|
timestamps.add(System.nanoTime());
|
||||||
public void run() {
|
try {
|
||||||
timestamps.add(System.nanoTime());
|
Thread.sleep(51);
|
||||||
try {
|
} catch (InterruptedException e) {
|
||||||
Thread.sleep(51);
|
// Ignore
|
||||||
} catch (InterruptedException e) {
|
|
||||||
// Ignore
|
|
||||||
}
|
|
||||||
allTimeStampsLatch.countDown();
|
|
||||||
}
|
}
|
||||||
|
allTimeStampsLatch.countDown();
|
||||||
}, 100, 100, TimeUnit.MILLISECONDS);
|
}, 100, 100, TimeUnit.MILLISECONDS);
|
||||||
allTimeStampsLatch.await();
|
allTimeStampsLatch.await();
|
||||||
assertTrue(f.cancel(true));
|
assertTrue(f.cancel(true));
|
||||||
@ -305,16 +283,13 @@ public class SingleThreadEventLoopTest {
|
|||||||
final int NUM_TASKS = 3;
|
final int NUM_TASKS = 3;
|
||||||
final AtomicInteger ranTasks = new AtomicInteger();
|
final AtomicInteger ranTasks = new AtomicInteger();
|
||||||
final CountDownLatch latch = new CountDownLatch(1);
|
final CountDownLatch latch = new CountDownLatch(1);
|
||||||
final Runnable task = new Runnable() {
|
final Runnable task = () -> {
|
||||||
@Override
|
ranTasks.incrementAndGet();
|
||||||
public void run() {
|
while (latch.getCount() > 0) {
|
||||||
ranTasks.incrementAndGet();
|
try {
|
||||||
while (latch.getCount() > 0) {
|
latch.await();
|
||||||
try {
|
} catch (InterruptedException e) {
|
||||||
latch.await();
|
// Ignored
|
||||||
} catch (InterruptedException e) {
|
|
||||||
// Ignored
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -380,12 +355,7 @@ public class SingleThreadEventLoopTest {
|
|||||||
final CountDownLatch latch = new CountDownLatch(1);
|
final CountDownLatch latch = new CountDownLatch(1);
|
||||||
Channel ch = new LocalChannel(loopA);
|
Channel ch = new LocalChannel(loopA);
|
||||||
ChannelPromise promise = ch.newPromise();
|
ChannelPromise promise = ch.newPromise();
|
||||||
promise.addListener(new ChannelFutureListener() {
|
promise.addListener((ChannelFutureListener) future -> latch.countDown());
|
||||||
@Override
|
|
||||||
public void operationComplete(ChannelFuture future) throws Exception {
|
|
||||||
latch.countDown();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Disable logging temporarily.
|
// Disable logging temporarily.
|
||||||
Logger root = (Logger) LoggerFactory.getLogger(org.slf4j.Logger.ROOT_LOGGER_NAME);
|
Logger root = (Logger) LoggerFactory.getLogger(org.slf4j.Logger.ROOT_LOGGER_NAME);
|
||||||
|
@ -22,6 +22,7 @@ import static org.junit.Assert.assertSame;
|
|||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
import static org.junit.Assert.fail;
|
import static org.junit.Assert.fail;
|
||||||
|
|
||||||
|
import io.netty.channel.ChannelOutboundInvoker;
|
||||||
import java.nio.channels.ClosedChannelException;
|
import java.nio.channels.ClosedChannelException;
|
||||||
import java.util.ArrayDeque;
|
import java.util.ArrayDeque;
|
||||||
import java.util.Queue;
|
import java.util.Queue;
|
||||||
@ -79,12 +80,7 @@ public class EmbeddedChannelTest {
|
|||||||
@Test(timeout = 2000)
|
@Test(timeout = 2000)
|
||||||
public void promiseDoesNotInfiniteLoop() throws InterruptedException {
|
public void promiseDoesNotInfiniteLoop() throws InterruptedException {
|
||||||
EmbeddedChannel channel = new EmbeddedChannel();
|
EmbeddedChannel channel = new EmbeddedChannel();
|
||||||
channel.closeFuture().addListener(new ChannelFutureListener() {
|
channel.closeFuture().addListener((ChannelFutureListener) future -> future.channel().close());
|
||||||
@Override
|
|
||||||
public void operationComplete(ChannelFuture future) throws Exception {
|
|
||||||
future.channel().close();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
channel.close().syncUninterruptibly();
|
channel.close().syncUninterruptibly();
|
||||||
}
|
}
|
||||||
@ -121,18 +117,8 @@ public class EmbeddedChannelTest {
|
|||||||
public void testScheduling() throws Exception {
|
public void testScheduling() throws Exception {
|
||||||
EmbeddedChannel ch = new EmbeddedChannel(new ChannelInboundHandlerAdapter());
|
EmbeddedChannel ch = new EmbeddedChannel(new ChannelInboundHandlerAdapter());
|
||||||
final CountDownLatch latch = new CountDownLatch(2);
|
final CountDownLatch latch = new CountDownLatch(2);
|
||||||
ScheduledFuture future = ch.eventLoop().schedule(new Runnable() {
|
ScheduledFuture future = ch.eventLoop().schedule(latch::countDown, 1, TimeUnit.SECONDS);
|
||||||
@Override
|
future.addListener((FutureListener) future1 -> latch.countDown());
|
||||||
public void run() {
|
|
||||||
latch.countDown();
|
|
||||||
}
|
|
||||||
}, 1, TimeUnit.SECONDS);
|
|
||||||
future.addListener(new FutureListener() {
|
|
||||||
@Override
|
|
||||||
public void operationComplete(Future future) throws Exception {
|
|
||||||
latch.countDown();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
long next = ch.runScheduledPendingTasks();
|
long next = ch.runScheduledPendingTasks();
|
||||||
assertTrue(next > 0);
|
assertTrue(next > 0);
|
||||||
// Sleep for the nanoseconds but also give extra 50ms as the clock my not be very precise and so fail the test
|
// Sleep for the nanoseconds but also give extra 50ms as the clock my not be very precise and so fail the test
|
||||||
@ -145,10 +131,7 @@ public class EmbeddedChannelTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testScheduledCancelled() throws Exception {
|
public void testScheduledCancelled() throws Exception {
|
||||||
EmbeddedChannel ch = new EmbeddedChannel(new ChannelInboundHandlerAdapter());
|
EmbeddedChannel ch = new EmbeddedChannel(new ChannelInboundHandlerAdapter());
|
||||||
ScheduledFuture<?> future = ch.eventLoop().schedule(new Runnable() {
|
ScheduledFuture<?> future = ch.eventLoop().schedule(() -> { }, 1, TimeUnit.DAYS);
|
||||||
@Override
|
|
||||||
public void run() { }
|
|
||||||
}, 1, TimeUnit.DAYS);
|
|
||||||
ch.finish();
|
ch.finish();
|
||||||
assertTrue(future.isCancelled());
|
assertTrue(future.isCancelled());
|
||||||
}
|
}
|
||||||
@ -200,35 +183,15 @@ public class EmbeddedChannelTest {
|
|||||||
// See https://github.com/netty/netty/issues/4316.
|
// See https://github.com/netty/netty/issues/4316.
|
||||||
@Test(timeout = 2000)
|
@Test(timeout = 2000)
|
||||||
public void testFireChannelInactiveAndUnregisteredOnClose() throws InterruptedException {
|
public void testFireChannelInactiveAndUnregisteredOnClose() throws InterruptedException {
|
||||||
testFireChannelInactiveAndUnregistered(new Action() {
|
testFireChannelInactiveAndUnregistered(ChannelOutboundInvoker::close);
|
||||||
@Override
|
testFireChannelInactiveAndUnregistered(channel -> channel.close(channel.newPromise()));
|
||||||
public ChannelFuture doRun(Channel channel) {
|
|
||||||
return channel.close();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
testFireChannelInactiveAndUnregistered(new Action() {
|
|
||||||
@Override
|
|
||||||
public ChannelFuture doRun(Channel channel) {
|
|
||||||
return channel.close(channel.newPromise());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(timeout = 2000)
|
@Test(timeout = 2000)
|
||||||
public void testFireChannelInactiveAndUnregisteredOnDisconnect() throws InterruptedException {
|
public void testFireChannelInactiveAndUnregisteredOnDisconnect() throws InterruptedException {
|
||||||
testFireChannelInactiveAndUnregistered(new Action() {
|
testFireChannelInactiveAndUnregistered(ChannelOutboundInvoker::disconnect);
|
||||||
@Override
|
|
||||||
public ChannelFuture doRun(Channel channel) {
|
|
||||||
return channel.disconnect();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
testFireChannelInactiveAndUnregistered(new Action() {
|
testFireChannelInactiveAndUnregistered(channel -> channel.disconnect(channel.newPromise()));
|
||||||
@Override
|
|
||||||
public ChannelFuture doRun(Channel channel) {
|
|
||||||
return channel.disconnect(channel.newPromise());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void testFireChannelInactiveAndUnregistered(Action action) throws InterruptedException {
|
private static void testFireChannelInactiveAndUnregistered(Action action) throws InterruptedException {
|
||||||
@ -237,13 +200,8 @@ public class EmbeddedChannelTest {
|
|||||||
@Override
|
@Override
|
||||||
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
|
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
|
||||||
latch.countDown();
|
latch.countDown();
|
||||||
ctx.executor().execute(new Runnable() {
|
// Should be executed.
|
||||||
@Override
|
ctx.executor().execute(latch::countDown);
|
||||||
public void run() {
|
|
||||||
// Should be executed.
|
|
||||||
latch.countDown();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -368,12 +326,7 @@ public class EmbeddedChannelTest {
|
|||||||
@Override
|
@Override
|
||||||
public void write(final ChannelHandlerContext ctx, final Object msg, final ChannelPromise promise)
|
public void write(final ChannelHandlerContext ctx, final Object msg, final ChannelPromise promise)
|
||||||
throws Exception {
|
throws Exception {
|
||||||
ctx.executor().execute(new Runnable() {
|
ctx.executor().execute(() -> ctx.write(msg, promise));
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
ctx.write(msg, promise);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
Object msg = new Object();
|
Object msg = new Object();
|
||||||
@ -391,11 +344,8 @@ public class EmbeddedChannelTest {
|
|||||||
@Override
|
@Override
|
||||||
public void write(final ChannelHandlerContext ctx, final Object msg, final ChannelPromise promise)
|
public void write(final ChannelHandlerContext ctx, final Object msg, final ChannelPromise promise)
|
||||||
throws Exception {
|
throws Exception {
|
||||||
ctx.executor().schedule(new Runnable() {
|
ctx.executor().schedule(() -> {
|
||||||
@Override
|
ctx.writeAndFlush(msg, promise);
|
||||||
public void run() {
|
|
||||||
ctx.writeAndFlush(msg, promise);
|
|
||||||
}
|
|
||||||
}, delay, TimeUnit.MILLISECONDS);
|
}, delay, TimeUnit.MILLISECONDS);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -117,13 +117,10 @@ public class LocalChannelTest {
|
|||||||
// Connect to the server
|
// Connect to the server
|
||||||
cc = cb.connect(sc.localAddress()).sync().channel();
|
cc = cb.connect(sc.localAddress()).sync().channel();
|
||||||
final Channel ccCpy = cc;
|
final Channel ccCpy = cc;
|
||||||
cc.eventLoop().execute(new Runnable() {
|
cc.eventLoop().execute(() -> {
|
||||||
@Override
|
// Send a message event up the pipeline.
|
||||||
public void run() {
|
ccCpy.pipeline().fireChannelRead("Hello, World");
|
||||||
// Send a message event up the pipeline.
|
latch.countDown();
|
||||||
ccCpy.pipeline().fireChannelRead("Hello, World");
|
|
||||||
latch.countDown();
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
assertTrue(latch.await(5, SECONDS));
|
assertTrue(latch.await(5, SECONDS));
|
||||||
|
|
||||||
@ -370,18 +367,10 @@ public class LocalChannelTest {
|
|||||||
|
|
||||||
final Channel ccCpy = cc;
|
final Channel ccCpy = cc;
|
||||||
// Make sure a write operation is executed in the eventloop
|
// Make sure a write operation is executed in the eventloop
|
||||||
cc.pipeline().lastContext().executor().execute(new Runnable() {
|
cc.pipeline().lastContext().executor().execute(() -> {
|
||||||
@Override
|
ChannelPromise promise = ccCpy.newPromise();
|
||||||
public void run() {
|
promise.addListener((ChannelFutureListener) future -> ccCpy.pipeline().lastContext().close());
|
||||||
ChannelPromise promise = ccCpy.newPromise();
|
ccCpy.writeAndFlush(data.retainedDuplicate(), promise);
|
||||||
promise.addListener(new ChannelFutureListener() {
|
|
||||||
@Override
|
|
||||||
public void operationComplete(ChannelFuture future) throws Exception {
|
|
||||||
ccCpy.pipeline().lastContext().close();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
ccCpy.writeAndFlush(data.retainedDuplicate(), promise);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
assertTrue(messageLatch.await(5, SECONDS));
|
assertTrue(messageLatch.await(5, SECONDS));
|
||||||
@ -501,18 +490,11 @@ public class LocalChannelTest {
|
|||||||
|
|
||||||
final Channel ccCpy = cc;
|
final Channel ccCpy = cc;
|
||||||
// Make sure a write operation is executed in the eventloop
|
// Make sure a write operation is executed in the eventloop
|
||||||
cc.pipeline().lastContext().executor().execute(new Runnable() {
|
cc.pipeline().lastContext().executor().execute(() -> {
|
||||||
@Override
|
ChannelPromise promise = ccCpy.newPromise();
|
||||||
public void run() {
|
promise.addListener((ChannelFutureListener) future ->
|
||||||
ChannelPromise promise = ccCpy.newPromise();
|
ccCpy.writeAndFlush(data2.retainedDuplicate(), ccCpy.newPromise()));
|
||||||
promise.addListener(new ChannelFutureListener() {
|
ccCpy.writeAndFlush(data.retainedDuplicate(), promise);
|
||||||
@Override
|
|
||||||
public void operationComplete(ChannelFuture future) throws Exception {
|
|
||||||
ccCpy.writeAndFlush(data2.retainedDuplicate(), ccCpy.newPromise());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
ccCpy.writeAndFlush(data.retainedDuplicate(), promise);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
assertTrue(messageLatch.await(5, SECONDS));
|
assertTrue(messageLatch.await(5, SECONDS));
|
||||||
@ -583,19 +565,13 @@ public class LocalChannelTest {
|
|||||||
|
|
||||||
final Channel ccCpy = cc;
|
final Channel ccCpy = cc;
|
||||||
// Make sure a write operation is executed in the eventloop
|
// Make sure a write operation is executed in the eventloop
|
||||||
cc.pipeline().lastContext().executor().execute(new Runnable() {
|
cc.pipeline().lastContext().executor().execute(() -> {
|
||||||
@Override
|
ChannelPromise promise = ccCpy.newPromise();
|
||||||
public void run() {
|
promise.addListener((ChannelFutureListener) future -> {
|
||||||
ChannelPromise promise = ccCpy.newPromise();
|
Channel serverChannelCpy = serverChannelRef.get();
|
||||||
promise.addListener(new ChannelFutureListener() {
|
serverChannelCpy.writeAndFlush(data2.retainedDuplicate(), serverChannelCpy.newPromise());
|
||||||
@Override
|
});
|
||||||
public void operationComplete(ChannelFuture future) throws Exception {
|
ccCpy.writeAndFlush(data.retainedDuplicate(), promise);
|
||||||
Channel serverChannelCpy = serverChannelRef.get();
|
|
||||||
serverChannelCpy.writeAndFlush(data2.retainedDuplicate(), serverChannelCpy.newPromise());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
ccCpy.writeAndFlush(data.retainedDuplicate(), promise);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
assertTrue(messageLatch.await(5, SECONDS));
|
assertTrue(messageLatch.await(5, SECONDS));
|
||||||
@ -665,20 +641,14 @@ public class LocalChannelTest {
|
|||||||
|
|
||||||
final Channel ccCpy = cc;
|
final Channel ccCpy = cc;
|
||||||
// Make sure a write operation is executed in the eventloop
|
// Make sure a write operation is executed in the eventloop
|
||||||
cc.pipeline().lastContext().executor().execute(new Runnable() {
|
cc.pipeline().lastContext().executor().execute(() -> {
|
||||||
@Override
|
ChannelPromise promise = ccCpy.newPromise();
|
||||||
public void run() {
|
promise.addListener((ChannelFutureListener) future -> {
|
||||||
ChannelPromise promise = ccCpy.newPromise();
|
Channel serverChannelCpy = serverChannelRef.get();
|
||||||
promise.addListener(new ChannelFutureListener() {
|
serverChannelCpy.writeAndFlush(
|
||||||
@Override
|
data2.retainedDuplicate(), serverChannelCpy.newPromise());
|
||||||
public void operationComplete(ChannelFuture future) throws Exception {
|
});
|
||||||
Channel serverChannelCpy = serverChannelRef.get();
|
ccCpy.writeAndFlush(data.retainedDuplicate(), promise);
|
||||||
serverChannelCpy.writeAndFlush(
|
|
||||||
data2.retainedDuplicate(), serverChannelCpy.newPromise());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
ccCpy.writeAndFlush(data.retainedDuplicate(), promise);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
assertTrue(messageLatch.await(5, SECONDS));
|
assertTrue(messageLatch.await(5, SECONDS));
|
||||||
@ -747,47 +717,34 @@ public class LocalChannelTest {
|
|||||||
ccCpy.closeFuture().addListener(clientChannelCloseLatch);
|
ccCpy.closeFuture().addListener(clientChannelCloseLatch);
|
||||||
|
|
||||||
// Make sure a write operation is executed in the eventloop
|
// Make sure a write operation is executed in the eventloop
|
||||||
cc.pipeline().lastContext().executor().execute(new Runnable() {
|
cc.pipeline().lastContext().executor().execute(() ->
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
ccCpy.writeAndFlush(data.retainedDuplicate(), ccCpy.newPromise())
|
ccCpy.writeAndFlush(data.retainedDuplicate(), ccCpy.newPromise())
|
||||||
.addListener(new ChannelFutureListener() {
|
.addListener((ChannelFutureListener) future -> {
|
||||||
@Override
|
serverChannelCpy.eventLoop().execute(() -> {
|
||||||
public void operationComplete(ChannelFuture future) throws Exception {
|
// The point of this test is to write while the peer is closed, so we should
|
||||||
serverChannelCpy.eventLoop().execute(new Runnable() {
|
// ensure the peer is actually closed before we write.
|
||||||
@Override
|
int waitCount = 0;
|
||||||
public void run() {
|
while (ccCpy.isOpen()) {
|
||||||
// The point of this test is to write while the peer is closed, so we should
|
try {
|
||||||
// ensure the peer is actually closed before we write.
|
Thread.sleep(50);
|
||||||
int waitCount = 0;
|
} catch (InterruptedException ignored) {
|
||||||
while (ccCpy.isOpen()) {
|
// ignored
|
||||||
try {
|
|
||||||
Thread.sleep(50);
|
|
||||||
} catch (InterruptedException ignored) {
|
|
||||||
// ignored
|
|
||||||
}
|
|
||||||
if (++waitCount > 5) {
|
|
||||||
fail();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
serverChannelCpy.writeAndFlush(data2.retainedDuplicate(),
|
|
||||||
serverChannelCpy.newPromise())
|
|
||||||
.addListener(new ChannelFutureListener() {
|
|
||||||
@Override
|
|
||||||
public void operationComplete(ChannelFuture future) throws Exception {
|
|
||||||
if (!future.isSuccess() &&
|
|
||||||
future.cause() instanceof ClosedChannelException) {
|
|
||||||
writeFailLatch.countDown();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
ccCpy.close();
|
|
||||||
}
|
}
|
||||||
});
|
if (++waitCount > 5) {
|
||||||
}
|
fail();
|
||||||
});
|
}
|
||||||
|
}
|
||||||
|
serverChannelCpy.writeAndFlush(data2.retainedDuplicate(),
|
||||||
|
serverChannelCpy.newPromise())
|
||||||
|
.addListener((ChannelFutureListener) future1 -> {
|
||||||
|
if (!future1.isSuccess() &&
|
||||||
|
future1.cause() instanceof ClosedChannelException) {
|
||||||
|
writeFailLatch.countDown();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
ccCpy.close();
|
||||||
|
}));
|
||||||
|
|
||||||
assertTrue(serverMessageLatch.await(5, SECONDS));
|
assertTrue(serverMessageLatch.await(5, SECONDS));
|
||||||
assertTrue(writeFailLatch.await(5, SECONDS));
|
assertTrue(writeFailLatch.await(5, SECONDS));
|
||||||
@ -952,12 +909,9 @@ public class LocalChannelTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static void writeAndFlushReadOnSuccess(final ChannelHandlerContext ctx, Object msg) {
|
private static void writeAndFlushReadOnSuccess(final ChannelHandlerContext ctx, Object msg) {
|
||||||
ctx.writeAndFlush(msg).addListener(new ChannelFutureListener() {
|
ctx.writeAndFlush(msg).addListener((ChannelFutureListener) future -> {
|
||||||
@Override
|
if (future.isSuccess()) {
|
||||||
public void operationComplete(ChannelFuture future) {
|
ctx.read();
|
||||||
if (future.isSuccess()) {
|
|
||||||
ctx.read();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -1182,12 +1136,9 @@ public class LocalChannelTest {
|
|||||||
if (!autoRead) {
|
if (!autoRead) {
|
||||||
// The read will be scheduled 100ms in the future to ensure we not receive any
|
// The read will be scheduled 100ms in the future to ensure we not receive any
|
||||||
// channelRead calls in the meantime.
|
// channelRead calls in the meantime.
|
||||||
ctx.executor().schedule(new Runnable() {
|
ctx.executor().schedule(() -> {
|
||||||
@Override
|
read = 0;
|
||||||
public void run() {
|
ctx.read();
|
||||||
read = 0;
|
|
||||||
ctx.read();
|
|
||||||
}
|
|
||||||
}, 100, TimeUnit.MILLISECONDS);
|
}, 100, TimeUnit.MILLISECONDS);
|
||||||
} else {
|
} else {
|
||||||
read = 0;
|
read = 0;
|
||||||
|
@ -266,12 +266,9 @@ public class LocalTransportThreadModelTest {
|
|||||||
final int end = i + ELEMS_PER_ROUNDS;
|
final int end = i + ELEMS_PER_ROUNDS;
|
||||||
i = end;
|
i = end;
|
||||||
|
|
||||||
ch.eventLoop().execute(new Runnable() {
|
ch.eventLoop().execute(() -> {
|
||||||
@Override
|
for (int j = start; j < end; j ++) {
|
||||||
public void run() {
|
ch.pipeline().fireChannelRead(Integer.valueOf(j));
|
||||||
for (int j = start; j < end; j ++) {
|
|
||||||
ch.pipeline().fireChannelRead(Integer.valueOf(j));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -304,14 +301,11 @@ public class LocalTransportThreadModelTest {
|
|||||||
final int end = i + ELEMS_PER_ROUNDS;
|
final int end = i + ELEMS_PER_ROUNDS;
|
||||||
i = end;
|
i = end;
|
||||||
|
|
||||||
ch.pipeline().context(h6).executor().execute(new Runnable() {
|
ch.pipeline().context(h6).executor().execute(() -> {
|
||||||
@Override
|
for (int j = start; j < end; j ++) {
|
||||||
public void run() {
|
ch.write(Integer.valueOf(j));
|
||||||
for (int j = start; j < end; j ++) {
|
|
||||||
ch.write(Integer.valueOf(j));
|
|
||||||
}
|
|
||||||
ch.flush();
|
|
||||||
}
|
}
|
||||||
|
ch.flush();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,12 +83,7 @@ public class LocalTransportThreadModelTest2 {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
localChannel.eventLoop().execute(new Runnable() {
|
localChannel.eventLoop().execute(() -> close(localChannel, localRegistrationHandler));
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
close(localChannel, localRegistrationHandler);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Wait until the connection is closed or the connection attempt fails.
|
// Wait until the connection is closed or the connection attempt fails.
|
||||||
localChannel.closeFuture().awaitUninterruptibly();
|
localChannel.closeFuture().awaitUninterruptibly();
|
||||||
|
@ -152,25 +152,22 @@ public class LocalTransportThreadModelTest3 {
|
|||||||
|
|
||||||
Throwable cause = new Throwable();
|
Throwable cause = new Throwable();
|
||||||
|
|
||||||
Thread pipelineModifier = new Thread(new Runnable() {
|
Thread pipelineModifier = new Thread(() -> {
|
||||||
@Override
|
Random random = new Random();
|
||||||
public void run() {
|
|
||||||
Random random = new Random();
|
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
try {
|
try {
|
||||||
Thread.sleep(100);
|
Thread.sleep(100);
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
if (!ch.isRegistered()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
//EventForwardHandler forwardHandler = forwarders[random.nextInt(forwarders.length)];
|
|
||||||
ChannelHandler handler = ch.pipeline().removeFirst();
|
|
||||||
ch.pipeline().addBefore(groups[random.nextInt(groups.length)].next(), "recorder",
|
|
||||||
UUID.randomUUID().toString(), handler);
|
|
||||||
}
|
}
|
||||||
|
if (!ch.isRegistered()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
//EventForwardHandler forwardHandler = forwarders[random.nextInt(forwarders.length)];
|
||||||
|
ChannelHandler handler = ch.pipeline().removeFirst();
|
||||||
|
ch.pipeline().addBefore(groups[random.nextInt(groups.length)].next(), "recorder",
|
||||||
|
UUID.randomUUID().toString(), handler);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
pipelineModifier.setDaemon(true);
|
pipelineModifier.setDaemon(true);
|
||||||
|
@ -23,7 +23,6 @@ import io.netty.channel.MultithreadEventLoopGroup;
|
|||||||
import io.netty.channel.SelectStrategy;
|
import io.netty.channel.SelectStrategy;
|
||||||
import io.netty.channel.SelectStrategyFactory;
|
import io.netty.channel.SelectStrategyFactory;
|
||||||
import io.netty.channel.SingleThreadEventLoop;
|
import io.netty.channel.SingleThreadEventLoop;
|
||||||
|
|
||||||
import io.netty.channel.socket.ServerSocketChannel;
|
import io.netty.channel.socket.ServerSocketChannel;
|
||||||
import io.netty.channel.socket.nio.NioServerSocketChannel;
|
import io.netty.channel.socket.nio.NioServerSocketChannel;
|
||||||
import io.netty.util.IntSupplier;
|
import io.netty.util.IntSupplier;
|
||||||
@ -38,7 +37,6 @@ import java.nio.channels.SelectionKey;
|
|||||||
import java.nio.channels.Selector;
|
import java.nio.channels.Selector;
|
||||||
import java.nio.channels.SocketChannel;
|
import java.nio.channels.SocketChannel;
|
||||||
import java.nio.channels.spi.SelectorProvider;
|
import java.nio.channels.spi.SelectorProvider;
|
||||||
import java.util.concurrent.Callable;
|
|
||||||
import java.util.concurrent.CountDownLatch;
|
import java.util.concurrent.CountDownLatch;
|
||||||
import java.util.concurrent.RejectedExecutionException;
|
import java.util.concurrent.RejectedExecutionException;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
@ -66,35 +64,15 @@ public class NioEventLoopTest extends AbstractEventLoopTest {
|
|||||||
Channel channel = new NioServerSocketChannel(loop, loop);
|
Channel channel = new NioServerSocketChannel(loop, loop);
|
||||||
channel.register().syncUninterruptibly();
|
channel.register().syncUninterruptibly();
|
||||||
|
|
||||||
Selector selector = loop.submit(new Callable<Selector>() {
|
Selector selector = loop.submit(nioHandler::unwrappedSelector).syncUninterruptibly().getNow();
|
||||||
@Override
|
|
||||||
public Selector call() throws Exception {
|
|
||||||
return nioHandler.unwrappedSelector();
|
|
||||||
}
|
|
||||||
}).syncUninterruptibly().getNow();
|
|
||||||
|
|
||||||
assertSame(selector, loop.submit(new Callable<Selector>() {
|
assertSame(selector, loop.submit(nioHandler::unwrappedSelector).syncUninterruptibly().getNow());
|
||||||
@Override
|
|
||||||
public Selector call() throws Exception {
|
|
||||||
return nioHandler.unwrappedSelector();
|
|
||||||
}
|
|
||||||
}).syncUninterruptibly().getNow());
|
|
||||||
assertTrue(selector.isOpen());
|
assertTrue(selector.isOpen());
|
||||||
|
|
||||||
// Submit to the EventLoop so we are sure its really executed in a non-async manner.
|
// Submit to the EventLoop so we are sure its really executed in a non-async manner.
|
||||||
loop.submit(new Runnable() {
|
loop.submit(nioHandler::rebuildSelector).syncUninterruptibly();
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
nioHandler.rebuildSelector();
|
|
||||||
}
|
|
||||||
}).syncUninterruptibly();
|
|
||||||
|
|
||||||
Selector newSelector = loop.submit(new Callable<Selector>() {
|
Selector newSelector = loop.submit(nioHandler::unwrappedSelector).syncUninterruptibly().getNow();
|
||||||
@Override
|
|
||||||
public Selector call() throws Exception {
|
|
||||||
return nioHandler.unwrappedSelector();
|
|
||||||
}
|
|
||||||
}).syncUninterruptibly().getNow();
|
|
||||||
assertTrue(newSelector.isOpen());
|
assertTrue(newSelector.isOpen());
|
||||||
assertNotSame(selector, newSelector);
|
assertNotSame(selector, newSelector);
|
||||||
assertFalse(selector.isOpen());
|
assertFalse(selector.isOpen());
|
||||||
@ -110,11 +88,8 @@ public class NioEventLoopTest extends AbstractEventLoopTest {
|
|||||||
EventLoopGroup group = new MultithreadEventLoopGroup(1, NioHandler.newFactory());
|
EventLoopGroup group = new MultithreadEventLoopGroup(1, NioHandler.newFactory());
|
||||||
|
|
||||||
final EventLoop el = group.next();
|
final EventLoop el = group.next();
|
||||||
Future<?> future = el.schedule(new Runnable() {
|
Future<?> future = el.schedule(() -> {
|
||||||
@Override
|
// NOOP
|
||||||
public void run() {
|
|
||||||
// NOOP
|
|
||||||
}
|
|
||||||
}, Long.MAX_VALUE, TimeUnit.MILLISECONDS);
|
}, Long.MAX_VALUE, TimeUnit.MILLISECONDS);
|
||||||
|
|
||||||
assertFalse(future.awaitUninterruptibly(1000));
|
assertFalse(future.awaitUninterruptibly(1000));
|
||||||
@ -127,48 +102,25 @@ public class NioEventLoopTest extends AbstractEventLoopTest {
|
|||||||
final NioHandler nioHandler = (NioHandler) NioHandler.newFactory().newHandler();
|
final NioHandler nioHandler = (NioHandler) NioHandler.newFactory().newHandler();
|
||||||
EventLoop loop = new SingleThreadEventLoop(new DefaultThreadFactory("ioPool"), nioHandler);
|
EventLoop loop = new SingleThreadEventLoop(new DefaultThreadFactory("ioPool"), nioHandler);
|
||||||
try {
|
try {
|
||||||
Selector selector = loop.submit(new Callable<Selector>() {
|
Selector selector = loop.submit(nioHandler::unwrappedSelector).syncUninterruptibly().getNow();
|
||||||
@Override
|
|
||||||
public Selector call() throws Exception {
|
|
||||||
return nioHandler.unwrappedSelector();
|
|
||||||
}
|
|
||||||
}).syncUninterruptibly().getNow();
|
|
||||||
assertTrue(selector.isOpen());
|
assertTrue(selector.isOpen());
|
||||||
|
|
||||||
loop.submit(new Runnable() {
|
loop.submit(() -> {
|
||||||
@Override
|
// Interrupt the thread which should not end-up in a busy spin and
|
||||||
public void run() {
|
// so the selector should not have been rebuild.
|
||||||
// Interrupt the thread which should not end-up in a busy spin and
|
Thread.currentThread().interrupt();
|
||||||
// so the selector should not have been rebuild.
|
|
||||||
Thread.currentThread().interrupt();
|
|
||||||
}
|
|
||||||
}).syncUninterruptibly();
|
}).syncUninterruptibly();
|
||||||
|
|
||||||
assertTrue(selector.isOpen());
|
assertTrue(selector.isOpen());
|
||||||
|
|
||||||
final CountDownLatch latch = new CountDownLatch(2);
|
final CountDownLatch latch = new CountDownLatch(2);
|
||||||
loop.submit(new Runnable() {
|
loop.submit(latch::countDown).syncUninterruptibly();
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
latch.countDown();
|
|
||||||
}
|
|
||||||
}).syncUninterruptibly();
|
|
||||||
|
|
||||||
loop.schedule(new Runnable() {
|
loop.schedule(latch::countDown, 2, TimeUnit.SECONDS).syncUninterruptibly();
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
latch.countDown();
|
|
||||||
}
|
|
||||||
}, 2, TimeUnit.SECONDS).syncUninterruptibly();
|
|
||||||
|
|
||||||
latch.await();
|
latch.await();
|
||||||
|
|
||||||
assertSame(selector, loop.submit(new Callable<Selector>() {
|
assertSame(selector, loop.submit(nioHandler::unwrappedSelector).syncUninterruptibly().getNow());
|
||||||
@Override
|
|
||||||
public Selector call() throws Exception {
|
|
||||||
return nioHandler.unwrappedSelector();
|
|
||||||
}
|
|
||||||
}).syncUninterruptibly().getNow());
|
|
||||||
assertTrue(selector.isOpen());
|
assertTrue(selector.isOpen());
|
||||||
} finally {
|
} finally {
|
||||||
loop.shutdownGracefully();
|
loop.shutdownGracefully();
|
||||||
@ -190,9 +142,7 @@ public class NioEventLoopTest extends AbstractEventLoopTest {
|
|||||||
|
|
||||||
final CountDownLatch latch = new CountDownLatch(1);
|
final CountDownLatch latch = new CountDownLatch(1);
|
||||||
|
|
||||||
loop.execute(new Runnable() {
|
loop.execute(() ->
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
nioHandler.register(selectableChannel, SelectionKey.OP_CONNECT, new NioTask<SocketChannel>() {
|
nioHandler.register(selectableChannel, SelectionKey.OP_CONNECT, new NioTask<SocketChannel>() {
|
||||||
@Override
|
@Override
|
||||||
public void channelReady(SocketChannel ch, SelectionKey key) {
|
public void channelReady(SocketChannel ch, SelectionKey key) {
|
||||||
@ -202,9 +152,7 @@ public class NioEventLoopTest extends AbstractEventLoopTest {
|
|||||||
@Override
|
@Override
|
||||||
public void channelUnregistered(SocketChannel ch, Throwable cause) {
|
public void channelUnregistered(SocketChannel ch, Throwable cause) {
|
||||||
}
|
}
|
||||||
});
|
}));
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
latch.await();
|
latch.await();
|
||||||
|
|
||||||
@ -219,27 +167,21 @@ public class NioEventLoopTest extends AbstractEventLoopTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testTaskRemovalOnShutdownThrowsNoUnsupportedOperationException() throws Exception {
|
public void testTaskRemovalOnShutdownThrowsNoUnsupportedOperationException() throws Exception {
|
||||||
final AtomicReference<Throwable> error = new AtomicReference<>();
|
final AtomicReference<Throwable> error = new AtomicReference<>();
|
||||||
final Runnable task = new Runnable() {
|
final Runnable task = () -> {
|
||||||
@Override
|
// NOOP
|
||||||
public void run() {
|
|
||||||
// NOOP
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
// Just run often enough to trigger it normally.
|
// Just run often enough to trigger it normally.
|
||||||
for (int i = 0; i < 1000; i++) {
|
for (int i = 0; i < 1000; i++) {
|
||||||
EventLoopGroup group = new MultithreadEventLoopGroup(1, NioHandler.newFactory());
|
EventLoopGroup group = new MultithreadEventLoopGroup(1, NioHandler.newFactory());
|
||||||
final EventLoop loop = group.next();
|
final EventLoop loop = group.next();
|
||||||
|
|
||||||
Thread t = new Thread(new Runnable() {
|
Thread t = new Thread(() -> {
|
||||||
@Override
|
try {
|
||||||
public void run() {
|
for (;;) {
|
||||||
try {
|
loop.execute(task);
|
||||||
for (;;) {
|
|
||||||
loop.execute(task);
|
|
||||||
}
|
|
||||||
} catch (Throwable cause) {
|
|
||||||
error.set(cause);
|
|
||||||
}
|
}
|
||||||
|
} catch (Throwable cause) {
|
||||||
|
error.set(cause);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
t.start();
|
t.start();
|
||||||
@ -255,24 +197,19 @@ public class NioEventLoopTest extends AbstractEventLoopTest {
|
|||||||
public void testRebuildSelectorOnIOException() throws InterruptedException {
|
public void testRebuildSelectorOnIOException() throws InterruptedException {
|
||||||
final CountDownLatch latch = new CountDownLatch(1);
|
final CountDownLatch latch = new CountDownLatch(1);
|
||||||
final CountDownLatch strategyLatch = new CountDownLatch(1);
|
final CountDownLatch strategyLatch = new CountDownLatch(1);
|
||||||
SelectStrategyFactory selectStrategyFactory = new SelectStrategyFactory() {
|
SelectStrategyFactory selectStrategyFactory = () -> new SelectStrategy() {
|
||||||
|
|
||||||
|
private boolean thrown;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SelectStrategy newSelectStrategy() {
|
public int calculateStrategy(IntSupplier selectSupplier, boolean hasTasks) throws Exception {
|
||||||
return new SelectStrategy() {
|
strategyLatch.await();
|
||||||
|
if (!thrown) {
|
||||||
private boolean thrown;
|
thrown = true;
|
||||||
|
throw new IOException();
|
||||||
@Override
|
}
|
||||||
public int calculateStrategy(IntSupplier selectSupplier, boolean hasTasks) throws Exception {
|
latch.countDown();
|
||||||
strategyLatch.await();
|
return -1;
|
||||||
if (!thrown) {
|
|
||||||
thrown = true;
|
|
||||||
throw new IOException();
|
|
||||||
}
|
|
||||||
latch.countDown();
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -289,12 +226,7 @@ public class NioEventLoopTest extends AbstractEventLoopTest {
|
|||||||
|
|
||||||
latch.await();
|
latch.await();
|
||||||
|
|
||||||
Selector newSelector = loop.submit(new Callable<Selector>() {
|
Selector newSelector = loop.submit(nioHandler::unwrappedSelector).syncUninterruptibly().getNow();
|
||||||
@Override
|
|
||||||
public Selector call() throws Exception {
|
|
||||||
return nioHandler.unwrappedSelector();
|
|
||||||
}
|
|
||||||
}).syncUninterruptibly().getNow();
|
|
||||||
assertTrue(newSelector.isOpen());
|
assertTrue(newSelector.isOpen());
|
||||||
assertNotSame(selector, newSelector);
|
assertNotSame(selector, newSelector);
|
||||||
assertFalse(selector.isOpen());
|
assertFalse(selector.isOpen());
|
||||||
|
@ -132,12 +132,9 @@ public class NioSocketChannelTest extends AbstractNioChannelTest<NioSocketChanne
|
|||||||
// Trigger a gathering write by writing two buffers.
|
// Trigger a gathering write by writing two buffers.
|
||||||
ctx.write(Unpooled.wrappedBuffer(new byte[] { 'a' }));
|
ctx.write(Unpooled.wrappedBuffer(new byte[] { 'a' }));
|
||||||
ChannelFuture f = ctx.write(Unpooled.wrappedBuffer(new byte[] { 'b' }));
|
ChannelFuture f = ctx.write(Unpooled.wrappedBuffer(new byte[] { 'b' }));
|
||||||
f.addListener(new ChannelFutureListener() {
|
f.addListener((ChannelFutureListener) future -> {
|
||||||
@Override
|
// This message must be flushed
|
||||||
public void operationComplete(ChannelFuture future) throws Exception {
|
ctx.writeAndFlush(Unpooled.wrappedBuffer(new byte[]{'c'}));
|
||||||
// This message must be flushed
|
|
||||||
ctx.writeAndFlush(Unpooled.wrappedBuffer(new byte[]{'c'}));
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
ctx.flush();
|
ctx.flush();
|
||||||
}
|
}
|
||||||
@ -197,12 +194,9 @@ public class NioSocketChannelTest extends AbstractNioChannelTest<NioSocketChanne
|
|||||||
// As soon as the channel becomes active re-register it to another
|
// As soon as the channel becomes active re-register it to another
|
||||||
// EventLoop. After this is done we should still receive the data that
|
// EventLoop. After this is done we should still receive the data that
|
||||||
// was written to the channel.
|
// was written to the channel.
|
||||||
ctx.deregister().addListener(new ChannelFutureListener() {
|
ctx.deregister().addListener((ChannelFutureListener) cf -> {
|
||||||
@Override
|
Channel channel = cf.channel();
|
||||||
public void operationComplete(ChannelFuture cf) {
|
channel.register();
|
||||||
Channel channel = cf.channel();
|
|
||||||
channel.register();
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user