001: /*
002: * Copyright 2000-2006 Sun Microsystems, Inc. All Rights Reserved.
003: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004: *
005: * This code is free software; you can redistribute it and/or modify it
006: * under the terms of the GNU General Public License version 2 only, as
007: * published by the Free Software Foundation. Sun designates this
008: * particular file as subject to the "Classpath" exception as provided
009: * by Sun in the LICENSE file that accompanied this code.
010: *
011: * This code is distributed in the hope that it will be useful, but WITHOUT
012: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014: * version 2 for more details (a copy is included in the LICENSE file that
015: * accompanied this code).
016: *
017: * You should have received a copy of the GNU General Public License version
018: * 2 along with this work; if not, write to the Free Software Foundation,
019: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020: *
021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022: * CA 95054 USA or visit www.sun.com if you need additional information or
023: * have any questions.
024: */
025:
026: package sun.nio.ch;
027:
028: import java.io.*;
029: import java.nio.ByteBuffer;
030: import java.nio.channels.*;
031: import java.nio.channels.spi.*;
032:
033: class SourceChannelImpl extends Pipe.SourceChannel implements SelChImpl {
034:
035: // Used to make native read and write calls
036: private static NativeDispatcher nd;
037:
038: // The file descriptor associated with this channel
039: FileDescriptor fd;
040:
041: // fd value needed for dev/poll. This value will remain valid
042: // even after the value in the file descriptor object has been set to -1
043: int fdVal;
044:
045: // ID of native thread doing read, for signalling
046: private volatile long thread = 0;
047:
048: // Lock held by current reading thread
049: private final Object lock = new Object();
050:
051: // Lock held by any thread that modifies the state fields declared below
052: // DO NOT invoke a blocking I/O operation while holding this lock!
053: private final Object stateLock = new Object();
054:
055: // -- The following fields are protected by stateLock
056:
057: // Channel state
058: private static final int ST_UNINITIALIZED = -1;
059: private static final int ST_INUSE = 0;
060: private static final int ST_KILLED = 1;
061: private volatile int state = ST_UNINITIALIZED;
062:
063: // -- End of fields protected by stateLock
064:
065: public FileDescriptor getFD() {
066: return fd;
067: }
068:
069: public int getFDVal() {
070: return fdVal;
071: }
072:
073: SourceChannelImpl(SelectorProvider sp, FileDescriptor fd) {
074: super (sp);
075: this .fd = fd;
076: this .fdVal = IOUtil.fdVal(fd);
077: this .state = ST_INUSE;
078: }
079:
080: protected void implCloseSelectableChannel() throws IOException {
081: synchronized (stateLock) {
082: nd.preClose(fd);
083: long th = thread;
084: if (th != 0)
085: NativeThread.signal(th);
086: if (!isRegistered())
087: kill();
088: }
089: }
090:
091: public void kill() throws IOException {
092: synchronized (stateLock) {
093: if (state == ST_KILLED)
094: return;
095: if (state == ST_UNINITIALIZED) {
096: state = ST_KILLED;
097: return;
098: }
099: assert !isOpen() && !isRegistered();
100: nd.close(fd);
101: state = ST_KILLED;
102: }
103: }
104:
105: protected void implConfigureBlocking(boolean block)
106: throws IOException {
107: IOUtil.configureBlocking(fd, block);
108: }
109:
110: public boolean translateReadyOps(int ops, int initialOps,
111: SelectionKeyImpl sk) {
112: int intOps = sk.nioInterestOps(); // Do this just once, it synchronizes
113: int oldOps = sk.nioReadyOps();
114: int newOps = initialOps;
115:
116: if ((ops & PollArrayWrapper.POLLNVAL) != 0)
117: throw new Error("POLLNVAL detected");
118:
119: if ((ops & (PollArrayWrapper.POLLERR | PollArrayWrapper.POLLHUP)) != 0) {
120: newOps = intOps;
121: sk.nioReadyOps(newOps);
122: return (newOps & ~oldOps) != 0;
123: }
124:
125: if (((ops & PollArrayWrapper.POLLIN) != 0)
126: && ((intOps & SelectionKey.OP_READ) != 0))
127: newOps |= SelectionKey.OP_READ;
128:
129: sk.nioReadyOps(newOps);
130: return (newOps & ~oldOps) != 0;
131: }
132:
133: public boolean translateAndUpdateReadyOps(int ops,
134: SelectionKeyImpl sk) {
135: return translateReadyOps(ops, sk.nioReadyOps(), sk);
136: }
137:
138: public boolean translateAndSetReadyOps(int ops, SelectionKeyImpl sk) {
139: return translateReadyOps(ops, 0, sk);
140: }
141:
142: public void translateAndSetInterestOps(int ops, SelectionKeyImpl sk) {
143: if (ops == SelectionKey.OP_READ)
144: ops = PollArrayWrapper.POLLIN;
145: sk.selector.putEventOps(sk, ops);
146: }
147:
148: private void ensureOpen() throws IOException {
149: if (!isOpen())
150: throw new ClosedChannelException();
151: }
152:
153: public int read(ByteBuffer dst) throws IOException {
154: ensureOpen();
155: synchronized (lock) {
156: int n = 0;
157: try {
158: begin();
159: if (!isOpen())
160: return 0;
161: thread = NativeThread.current();
162: do {
163: n = IOUtil.read(fd, dst, -1, nd, lock);
164: } while ((n == IOStatus.INTERRUPTED) && isOpen());
165: return IOStatus.normalize(n);
166: } finally {
167: thread = 0;
168: end((n > 0) || (n == IOStatus.UNAVAILABLE));
169: assert IOStatus.check(n);
170: }
171: }
172: }
173:
174: public long read(ByteBuffer[] dsts, int offset, int length)
175: throws IOException {
176: if ((offset < 0) || (length < 0)
177: || (offset > dsts.length - length))
178: throw new IndexOutOfBoundsException();
179: return read(Util.subsequence(dsts, offset, length));
180: }
181:
182: public long read(ByteBuffer[] dsts) throws IOException {
183: if (dsts == null)
184: throw new NullPointerException();
185: ensureOpen();
186: synchronized (lock) {
187: long n = 0;
188: try {
189: begin();
190: if (!isOpen())
191: return 0;
192: thread = NativeThread.current();
193: do {
194: n = IOUtil.read(fd, dsts, nd);
195: } while ((n == IOStatus.INTERRUPTED) && isOpen());
196: return IOStatus.normalize(n);
197: } finally {
198: thread = 0;
199: end((n > 0) || (n == IOStatus.UNAVAILABLE));
200: assert IOStatus.check(n);
201: }
202: }
203: }
204:
205: static {
206: Util.load();
207: nd = new FileDispatcher();
208: }
209:
210: }
|