From 6143626427670b167b54501ead1a4ee50a3dcdc2 Mon Sep 17 00:00:00 2001 From: Norman Maurer Date: Fri, 12 Oct 2012 07:45:00 +0200 Subject: [PATCH] Cleanup of sctp code based on comments in #633 --- .../sctp/SctpMessageToMessageEncoder.java | 36 -------- .../aio/MethodHandleAioChannelFinder.java | 84 +++++++++++++++++++ 2 files changed, 84 insertions(+), 36 deletions(-) delete mode 100644 codec/src/main/java/io/netty/handler/codec/sctp/SctpMessageToMessageEncoder.java create mode 100644 transport/src/main/java/io/netty/channel/socket/aio/MethodHandleAioChannelFinder.java diff --git a/codec/src/main/java/io/netty/handler/codec/sctp/SctpMessageToMessageEncoder.java b/codec/src/main/java/io/netty/handler/codec/sctp/SctpMessageToMessageEncoder.java deleted file mode 100644 index fe94baa6fc..0000000000 --- a/codec/src/main/java/io/netty/handler/codec/sctp/SctpMessageToMessageEncoder.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package io.netty.handler.codec.sctp; - -import io.netty.buffer.ByteBuf; -import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.socket.SctpMessage; -import io.netty.handler.codec.MessageToMessageEncoder; - -public abstract class SctpMessageToMessageEncoder extends MessageToMessageEncoder { - - /** - * Returns {@code true} if and only if the specified message can be encoded by this encoder. - * - * @param msg the message - */ - public boolean isEncodable(Object msg) throws Exception { - return true; - } - - public abstract SctpMessage encode(ChannelHandlerContext ctx, I msg) throws Exception; -} diff --git a/transport/src/main/java/io/netty/channel/socket/aio/MethodHandleAioChannelFinder.java b/transport/src/main/java/io/netty/channel/socket/aio/MethodHandleAioChannelFinder.java new file mode 100644 index 0000000000..b4d8b593be --- /dev/null +++ b/transport/src/main/java/io/netty/channel/socket/aio/MethodHandleAioChannelFinder.java @@ -0,0 +1,84 @@ +/* + * Copyright 2012 The Netty Project + * + * The Netty Project licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.netty.channel.socket.aio; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.reflect.Field; +import java.util.HashMap; +import java.util.Map; + +public class MethodHandleAioChannelFinder implements AioChannelFinder { + private static volatile Map, MethodHandle> handleCache = new HashMap, MethodHandle>(); + + @Override + public AbstractAioChannel findChannel(Runnable command) throws Exception { + MethodHandle handle; + for (;;) { + handle = findHandle(command); + if (handle == null) { + return null; + } + Object next; + try { + next = handle.invokeExact(); + } catch (Throwable e) { + e.printStackTrace(); + throw new Exception("Unable to invoke handle " + handle, e); + } + if (next instanceof AbstractAioChannel) { + return (AbstractAioChannel) next; + } + command = (Runnable) next; + } + } + + private static MethodHandle findHandle(Object command) throws Exception { + Map, MethodHandle> handleCache = MethodHandleAioChannelFinder.handleCache; + Class commandType = command.getClass(); + MethodHandle res = handleCache.get(commandType); + if (res != null) { + return res; + } + + for (Field f: commandType.getDeclaredFields()) { + if (f.getType() == Runnable.class) { + return put(handleCache, commandType, f); + } + + // Check against the actual class as this is what will be used by the jdk + // if you use a final variable and pass it to a Runnable + if (f.getType().isAssignableFrom(AbstractAioChannel.class) + || f.getType() == Object.class) { + f.setAccessible(true); + Object candidate = f.get(command); + if (candidate instanceof AbstractAioChannel) { + return put(handleCache, commandType, f); + } + } + } + return null; + } + + private static MethodHandle put(Map, MethodHandle> oldCache, Class key, Field value) throws Exception { + MethodHandle handle = MethodHandles.lookup().findGetter(key, value.getName(), value.getType()); + Map, MethodHandle> newCache = new HashMap, MethodHandle>(oldCache.size()); + newCache.putAll(oldCache); + newCache.put(key, handle); + handleCache = newCache; + return handle; + } +}