/** {@inheritDoc} */ @SuppressWarnings("unchecked") @Override public <T> T createRingBufferProxy( final Class<T> proxyInterface, final Disruptor<ProxyMethodInvocation> disruptor, final OverflowStrategy overflowStrategy, final T implementation) { validator.validateAll(disruptor, proxyInterface); disruptor.handleEventsWith(createSingleImplementationHandlerChain(implementation)); final ArgumentHolderGenerator argumentHolderGenerator = new ArgumentHolderGenerator(classPool); argumentHolderGenerator.createArgumentHolderClass(proxyInterface); prefillArgumentHolderObjects(disruptor.getRingBuffer(), argumentHolderGenerator); final Map<Method, Invoker> methodToInvokerMap = createMethodToInvokerMap(proxyInterface, argumentHolderGenerator); return generateProxy( proxyInterface, disruptor.getRingBuffer(), methodToInvokerMap, overflowStrategy, argumentHolderGenerator); }
@SuppressWarnings("unchecked") private <T> Invoker generateInvoker( final Class<T> proxyInterface, final Method method, final ArgumentHolderGenerator argumentHolderGenerator) { final StringBuilder invokerClassName = new StringBuilder("_invoker") .append(proxyInterface.getSimpleName()) .append(method.getName()) .append('_') .append(getUniqueIdentifier()); final Class<?>[] parameterTypes = method.getParameterTypes(); for (final Class<?> paramType : parameterTypes) { if (paramType.isArray()) { invokerClassName.append(paramType.getComponentType().getSimpleName()).append("Array"); } else { invokerClassName.append(paramType.getSimpleName()); } } final CtClass ctClass = makeClass(classPool, invokerClassName.toString()); addInterface(ctClass, Invoker.class, classPool); makePublicFinal(ctClass); final StringBuilder methodSrc = new StringBuilder("public void invokeWithArgumentHolder(") .append("Object") .append(" implementation, Object argumentHolder) {\n"); if (parameterTypes.length != 0) { methodSrc .append("final ") .append(argumentHolderGenerator.getGeneratedClassName()) .append(" holder = ") .append("(") .append(argumentHolderGenerator.getGeneratedClassName()) .append(") argumentHolder;\n"); } methodSrc .append("((") .append(proxyInterface.getName().replace('$', '.')) .append(")implementation).") .append(method.getName()) .append('('); appendParametersFromArgumentHolder(parameterTypes, methodSrc, argumentHolderGenerator); methodSrc.append(");\n}\n"); return generateInvoker(ctClass, methodSrc); }
private void appendParametersFromArgumentHolder( final Class<?>[] parameterTypes, final StringBuilder methodSrc, final ArgumentHolderGenerator argumentHolderGenerator) { argumentHolderGenerator.resetFieldNames(); for (int i = 0; i < parameterTypes.length; i++) { final Class<?> parameterType = parameterTypes[i]; methodSrc .append("holder.") .append(argumentHolderGenerator.getNextFieldNameForType(parameterType)); if (i < parameterTypes.length - 1) { methodSrc.append(", "); } } }
private void prefillArgumentHolderObjects( final RingBuffer<ProxyMethodInvocation> ringBuffer, final ArgumentHolderGenerator argumentHolderGenerator) { final int bufferSize = ringBuffer.getBufferSize(); for (int i = 0; i < bufferSize; i++) { ringBuffer .get(i) .setArgumentHolder( (Resetable) instantiate(argumentHolderGenerator.getGeneratedClass(), new Class[] {})); } }
/** {@inheritDoc} */ @Override @SuppressWarnings("unchecked") public <T> T createRingBufferProxy( final Class<T> proxyInterface, final Disruptor<ProxyMethodInvocation> disruptor, final OverflowStrategy overflowStrategy, final T... implementations) { validator.validateAll(disruptor, proxyInterface); if (implementations.length < 1) { throw new IllegalArgumentException("Must have at least one implementation"); } else if (implementations.length == 1) { return createRingBufferProxy(proxyInterface, disruptor, overflowStrategy, implementations[0]); } final EventHandler<ProxyMethodInvocation>[] handlers = new EventHandler[implementations.length]; for (int i = 0; i < implementations.length; i++) { handlers[i] = createMultipleImplementationHandlerChain(implementations[i]); disruptor.handleEventsWith(handlers[i]); } disruptor.after(handlers).then(new ResetHandler()); final ArgumentHolderGenerator argumentHolderGenerator = new ArgumentHolderGenerator(classPool); argumentHolderGenerator.createArgumentHolderClass(proxyInterface); prefillArgumentHolderObjects(disruptor.getRingBuffer(), argumentHolderGenerator); final Map<Method, Invoker> methodToInvokerMap = createMethodToInvokerMap(proxyInterface, argumentHolderGenerator); return generateProxy( proxyInterface, disruptor.getRingBuffer(), methodToInvokerMap, overflowStrategy, argumentHolderGenerator); }
private void createRingBufferPublisherMethod( final CtClass ctClass, final Method method, final Invoker invoker, final OverflowStrategy overflowStrategy, final ArgumentHolderGenerator argumentHolderGenerator) { final StringBuilder methodSrc = new StringBuilder("public void ").append(method.getName()).append("("); final Class<?>[] parameterTypes = method.getParameterTypes(); char paramId = 'a'; for (int i = 0, parameterTypesLength = parameterTypes.length; i < parameterTypesLength; i++) { final Class<?> parameterType = parameterTypes[i]; if (parameterType.isArray()) { methodSrc .append(parameterType.getComponentType().getName()) .append("[] ") .append(paramId++); } else { methodSrc.append(parameterType.getName()).append(' ').append(paramId++); } if (i < parameterTypesLength - 1) { methodSrc.append(", "); } } methodSrc.append(")\n{\n"); methodSrc.append("messagePublicationListener.onPrePublish();\n"); handleOverflowStrategy(overflowStrategy, methodSrc); methodSrc .append("final long sequence = ringBuffer.next();\n") .append("try\n") .append("{\n") .append( "final ProxyMethodInvocation proxyMethodInvocation = (ProxyMethodInvocation) ringBuffer.get(sequence);\n"); final String argumentHolderClass = argumentHolderGenerator.getGeneratedClassName(); methodSrc .append("final ") .append(argumentHolderClass) .append(" holder = (") .append(argumentHolderClass) .append(") proxyMethodInvocation.getArgumentHolder();\n"); argumentHolderGenerator.resetFieldNames(); for (int i = 0; i < parameterTypes.length; i++) { final Class<?> parameterType = parameterTypes[i]; final String holderField = argumentHolderGenerator.getNextFieldNameForType(parameterType); methodSrc .append("holder.") .append(holderField) .append(" = ") .append((char) ('a' + i)) .append(";"); } methodSrc .append("proxyMethodInvocation.setInvoker(_") .append(invoker.getClass().getName()) .append(");\n") .append("}\n") .append("catch(Throwable t){t.printStackTrace();}\n") .append("finally\n") .append("{\n") .append("ringBuffer.publish(sequence);\n") .append("messagePublicationListener.onPostPublish();\n") .append("}\n"); methodSrc.append("}\n"); createMethod(ctClass, methodSrc.toString()); }