/** * Copyright 2014 Ricardo Padilha * * Licensed 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 net.dsys.snio.impl.buffer; import javax.annotation.Nonnegative; import javax.annotation.Nonnull; import net.dsys.commons.api.lang.Factory; import net.dsys.snio.api.buffer.MessageBufferConsumer; import net.dsys.snio.api.buffer.MessageBufferProducer; import net.dsys.snio.api.buffer.MessageBufferProvider; import net.dsys.snio.api.pool.KeyProcessor; /** * @author Ricardo Padilha */ public final class BlockingQueueProvider<T> implements MessageBufferProvider<T> { static final int INITIAL_SEQUENCE_VALUE = -1; private final BlockingBuffer<T> out; // app -> channel private final BlockingBuffer<T> in; // channel -> app private final BlockingQueueProducer<T> appOut; // app producer private final BlockingQueueConsumer<T> chnIn; // channel consumer private final MessageBufferProducer<T> chnOut; // channel producer private final MessageBufferConsumer<T> appIn; // app consumer private final boolean internalConsumer; BlockingQueueProvider(@Nonnegative final int capacity, @Nonnull final Factory<T> factory) { this.out = new BlockingBuffer<>(capacity); this.in = new BlockingBuffer<>(capacity); this.appOut = new BlockingQueueProducer<>(out, factory); this.chnIn = new BlockingQueueConsumer<>(out, factory); this.chnOut = new BlockingQueueProducer<>(in, factory); this.appIn = new BlockingQueueConsumer<>(in, factory); this.internalConsumer = true; } BlockingQueueProvider(@Nonnegative final int capacity, @Nonnull final Factory<T> factory, @Nonnull final MessageBufferConsumer<T> consumer) { if (consumer == null) { throw new NullPointerException("appIn == null"); } this.out = new BlockingBuffer<>(capacity); this.in = null; this.appOut = new BlockingQueueProducer<>(out, factory); this.chnIn = new BlockingQueueConsumer<>(out, factory); this.chnOut = consumer.createProducer(); this.appIn = consumer; this.internalConsumer = false; } /** * {@inheritDoc} */ @Override public MessageBufferProducer<T> getAppOutput(final KeyProcessor<T> processor) { appOut.setProcessor(processor); return appOut; } /** * {@inheritDoc} */ @Override public MessageBufferConsumer<T> getChannelInput() { return chnIn; } /** * {@inheritDoc} */ @Override public MessageBufferProducer<T> getChannelOutput() { return chnOut; } /** * {@inheritDoc} */ @Override public MessageBufferConsumer<T> getAppInput() { return appIn; } /** * {@inheritDoc} */ @Override public void close() { appOut.close(); chnIn.close(); if (internalConsumer) { ((BlockingQueueProducer<?>) chnOut).close(); ((BlockingQueueConsumer<?>) appIn).close(); } } public static <T> BlockingQueueConsumer<T> createConsumer(final int capacity, final Factory<T> factory) { final BlockingBuffer<T> buffer = new BlockingBuffer<>(capacity); final BlockingQueueConsumer<T> consumer = new BlockingQueueConsumer<>(buffer, factory); return consumer; } public static <T> MessageBufferProvider<T> createProvider(final int capacity, final Factory<T> factory) { return new BlockingQueueProvider<>(capacity, factory); } public static <T> Factory<MessageBufferProvider<T>> createProviderFactory(final int capacity, final Factory<T> factory) { return new ProviderFactory<>(capacity, factory); } public static <T> MessageBufferProvider<T> createProvider(final int capacity, final Factory<T> factory, final MessageBufferConsumer<T> consumer) { return new BlockingQueueProvider<>(capacity, factory, consumer); } public static <T> Factory<MessageBufferProvider<T>> createProviderFactory(final int capacity, final Factory<T> factory, final MessageBufferConsumer<T> consumer) { return new ProviderFactory<>(capacity, factory, consumer); } private static final class ProviderFactory<T> implements Factory<MessageBufferProvider<T>> { private final int capacity; private final Factory<T> factory; private final MessageBufferConsumer<T> consumer; ProviderFactory(@Nonnegative final int capacity, @Nonnull final Factory<T> factory) { if (capacity < 1) { throw new IllegalArgumentException("capacity < 1"); } if (factory == null) { throw new NullPointerException("factory == null"); } this.capacity = capacity; this.factory = factory; this.consumer = null; } ProviderFactory(@Nonnegative final int capacity, @Nonnull final Factory<T> factory, @Nonnull final MessageBufferConsumer<T> consumer) { if (capacity < 1) { throw new IllegalArgumentException("capacity < 1"); } if (factory == null) { throw new NullPointerException("factory == null"); } if (consumer == null) { throw new NullPointerException("consumer == null"); } this.capacity = capacity; this.factory = factory; this.consumer = consumer; } @Override public MessageBufferProvider<T> newInstance() { if (consumer != null) { return new BlockingQueueProvider<>(capacity, factory, consumer); } return new BlockingQueueProvider<>(capacity, factory); } } }