All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.xnio.channels.SplitStreamSinkChannel Maven / Gradle / Ivy

Go to download

This artifact provides a single jar that contains all classes required to use remote EJB and JMS, including all dependencies. It is intended for use by those not using maven, maven users should just import the EJB and JMS BOM's instead (shaded JAR's cause lots of problems with maven, as it is very easy to inadvertently end up with different versions on classes on the class path).

There is a newer version: 34.0.0.Final
Show newest version
/*
 * JBoss, Home of Professional Open Source
 *
 * Copyright 2012 Red Hat, Inc. and/or its affiliates.
 *
 * 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 org.xnio.channels;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
import org.xnio.ChannelListener;
import org.xnio.Option;
import org.xnio.XnioExecutor;
import org.xnio.XnioIoThread;
import org.xnio.XnioWorker;

import static org.xnio.Bits.*;
import static org.xnio.ChannelListeners.invokeChannelListener;

/**
 * A half-duplex (write side) wrapper for a full-duplex channel.
 *
 * @author David M. Lloyd
 */
public final class SplitStreamSinkChannel implements StreamSinkChannel, WriteListenerSettable, CloseListenerSettable {
    private final StreamSinkChannel delegate;

    private volatile int state;

    private ChannelListener writeListener;
    private ChannelListener closeListener;

    private static final int FLAG_DELEGATE_CONFIG = 1 << 0;
    private static final int FLAG_CLOSE_REQ = 1 << 1;
    private static final int FLAG_CLOSE_COMP = 1 << 2;

    private static final AtomicIntegerFieldUpdater stateUpdater = AtomicIntegerFieldUpdater.newUpdater(SplitStreamSinkChannel.class, "state");

    /**
     * Construct a new instance.
     *
     * @param delegate the delegate channel
     * @param delegateConfig {@code true} to delegate configuration, {@code false} otherwise
     */
    public SplitStreamSinkChannel(final StreamSinkChannel delegate, boolean delegateConfig) {
        this.delegate = delegate;
        state = delegateConfig ? FLAG_DELEGATE_CONFIG : 0;
        delegate.getWriteSetter().set(new ChannelListener() {
            public void handleEvent(final StreamSinkChannel channel) {
                invokeChannelListener(SplitStreamSinkChannel.this, writeListener);
            }
        });
    }

    /**
     * Construct a new instance which does not delegate configuration.
     *
     * @param delegate the delegate channel
     */
    public SplitStreamSinkChannel(final StreamSinkChannel delegate) {
        this(delegate, false);
    }

    public void setWriteListener(final ChannelListener writeListener) {
        this.writeListener = writeListener;
    }

    public ChannelListener getWriteListener() {
        return writeListener;
    }

    public void setCloseListener(final ChannelListener closeListener) {
        this.closeListener = closeListener;
    }

    public ChannelListener getCloseListener() {
        return closeListener;
    }

    public ChannelListener.Setter getCloseSetter() {
        return new CloseListenerSettable.Setter(this);
    }

    @Override
    public int writeFinal(ByteBuffer src) throws IOException {
        return delegate.writeFinal(src);
    }

    @Override
    public long writeFinal(ByteBuffer[] srcs, int offset, int length) throws IOException {
        return delegate.writeFinal(srcs, offset, length);
    }

    @Override
    public long writeFinal(ByteBuffer[] srcs) throws IOException {
        return delegate.writeFinal(srcs);
    }

    public ChannelListener.Setter getWriteSetter() {
        return new WriteListenerSettable.Setter(this);
    }

    public void shutdownWrites() throws IOException {
        int oldVal, newVal;
        do {
            oldVal = state;
            if (allAreSet(oldVal, FLAG_CLOSE_REQ)) {
                return;
            }
            newVal = oldVal | FLAG_CLOSE_REQ;
        } while (! stateUpdater.compareAndSet(this, oldVal, newVal));
        delegate.shutdownWrites();
    }

    public boolean isOpen() {
        return allAreClear(state, FLAG_CLOSE_REQ);
    }

    public void close() throws IOException {
        shutdownWrites();
        // best lame-duck effort; can't do any more than this really
        flush();
    }

    public boolean flush() throws IOException {
        int oldVal, newVal;
        oldVal = state;
        if (allAreSet(oldVal, FLAG_CLOSE_COMP)) {
            return true;
        }
        final boolean flushed = delegate.flush();
        if (! flushed) {
            return false;
        }
        do {
            if (allAreClear(oldVal, FLAG_CLOSE_REQ)) {
                return true;
            }
            newVal = oldVal | FLAG_CLOSE_COMP;
        } while (! stateUpdater.compareAndSet(this, oldVal, newVal));
        invokeChannelListener(this, closeListener);
        return true;
    }

    public long transferFrom(final FileChannel src, final long position, final long count) throws IOException {
        return delegate.transferFrom(src, position, count);
    }

    public long transferFrom(final StreamSourceChannel source, final long count, final ByteBuffer throughBuffer) throws IOException {
        return delegate.transferFrom(source, count, throughBuffer);
    }

    public int write(final ByteBuffer src) throws IOException {
        return delegate.write(src);
    }

    public long write(final ByteBuffer[] srcs, final int offset, final int length) throws IOException {
        return delegate.write(srcs, offset, length);
    }

    public long write(final ByteBuffer[] srcs) throws IOException {
        return delegate.write(srcs);
    }

    public void suspendWrites() {
        delegate.suspendWrites();
    }

    public void resumeWrites() {
        delegate.resumeWrites();
    }

    public boolean isWriteResumed() {
        return delegate.isWriteResumed();
    }

    public void wakeupWrites() {
        delegate.wakeupWrites();
    }

    public void awaitWritable() throws IOException {
        delegate.awaitWritable();
    }

    public void awaitWritable(final long time, final TimeUnit timeUnit) throws IOException {
        delegate.awaitWritable(time, timeUnit);
    }

    @Deprecated
    public XnioExecutor getWriteThread() {
        return delegate.getWriteThread();
    }

    public XnioIoThread getIoThread() {
        return delegate.getIoThread();
    }

    public XnioWorker getWorker() {
        return delegate.getWorker();
    }

    public  T setOption(final Option option, final T value) throws IllegalArgumentException, IOException {
        return allAreSet(state, FLAG_DELEGATE_CONFIG) ? delegate.setOption(option, value) : null;
    }

    public  T getOption(final Option option) throws IOException {
        return allAreSet(state, FLAG_DELEGATE_CONFIG) ? delegate.getOption(option) : null;
    }

    public boolean supportsOption(final Option option) {
        return allAreSet(state, FLAG_DELEGATE_CONFIG) ? delegate.supportsOption(option) : false;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy