blob: bc58ba9ab3c813c61be4958ca86c69ad5e485a46 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 2000-2006 Sun Microsystems, Inc. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26package sun.nio.ch;
27
28import java.io.*;
29import java.nio.ByteBuffer;
30import java.nio.channels.*;
31import java.nio.channels.spi.*;
32
33
34class SinkChannelImpl
35 extends Pipe.SinkChannel
36 implements SelChImpl
37{
38
39 // Used to make native read and write calls
40 private static NativeDispatcher nd;
41
42 // The file descriptor associated with this channel
43 FileDescriptor fd;
44
45 // fd value needed for dev/poll. This value will remain valid
46 // even after the value in the file descriptor object has been set to -1
47 int fdVal;
48
49 // ID of native thread doing write, for signalling
50 private volatile long thread = 0;
51
52 // Lock held by current reading thread
53 private final Object lock = new Object();
54
55 // Lock held by any thread that modifies the state fields declared below
56 // DO NOT invoke a blocking I/O operation while holding this lock!
57 private final Object stateLock = new Object();
58
59 // -- The following fields are protected by stateLock
60
61 // Channel state
62 private static final int ST_UNINITIALIZED = -1;
63 private static final int ST_INUSE = 0;
64 private static final int ST_KILLED = 1;
65 private volatile int state = ST_UNINITIALIZED;
66
67 // -- End of fields protected by stateLock
68
69
70 public FileDescriptor getFD() {
71 return fd;
72 }
73
74 public int getFDVal() {
75 return fdVal;
76 }
77
78 SinkChannelImpl(SelectorProvider sp, FileDescriptor fd) {
79 super(sp);
80 this.fd = fd;
81 this.fdVal = IOUtil.fdVal(fd);
82 this.state = ST_INUSE;
83 }
84
85 protected void implCloseSelectableChannel() throws IOException {
86 synchronized (stateLock) {
87 nd.preClose(fd);
88 long th = thread;
89 if (th != 0)
90 NativeThread.signal(th);
91 if (!isRegistered())
92 kill();
93 }
94 }
95
96 public void kill() throws IOException {
97 synchronized (stateLock) {
98 if (state == ST_KILLED)
99 return;
100 if (state == ST_UNINITIALIZED) {
101 state = ST_KILLED;
102 return;
103 }
104 assert !isOpen() && !isRegistered();
105 nd.close(fd);
106 state = ST_KILLED;
107 }
108 }
109
110 protected void implConfigureBlocking(boolean block) throws IOException {
111 IOUtil.configureBlocking(fd, block);
112 }
113
114 public boolean translateReadyOps(int ops, int initialOps,
115 SelectionKeyImpl sk) {
116 int intOps = sk.nioInterestOps();// Do this just once, it synchronizes
117 int oldOps = sk.nioReadyOps();
118 int newOps = initialOps;
119
120 if ((ops & PollArrayWrapper.POLLNVAL) != 0)
121 throw new Error("POLLNVAL detected");
122
123 if ((ops & (PollArrayWrapper.POLLERR
124 | PollArrayWrapper.POLLHUP)) != 0) {
125 newOps = intOps;
126 sk.nioReadyOps(newOps);
127 return (newOps & ~oldOps) != 0;
128 }
129
130 if (((ops & PollArrayWrapper.POLLOUT) != 0) &&
131 ((intOps & SelectionKey.OP_WRITE) != 0))
132 newOps |= SelectionKey.OP_WRITE;
133
134 sk.nioReadyOps(newOps);
135 return (newOps & ~oldOps) != 0;
136 }
137
138 public boolean translateAndUpdateReadyOps(int ops, SelectionKeyImpl sk) {
139 return translateReadyOps(ops, sk.nioReadyOps(), sk);
140 }
141
142 public boolean translateAndSetReadyOps(int ops, SelectionKeyImpl sk) {
143 return translateReadyOps(ops, 0, sk);
144 }
145
146 public void translateAndSetInterestOps(int ops, SelectionKeyImpl sk) {
147 if (ops == SelectionKey.OP_WRITE)
148 ops = PollArrayWrapper.POLLOUT;
149 sk.selector.putEventOps(sk, ops);
150 }
151
152 private void ensureOpen() throws IOException {
153 if (!isOpen())
154 throw new ClosedChannelException();
155 }
156
157 public int write(ByteBuffer src) throws IOException {
158 ensureOpen();
159 synchronized (lock) {
160 int n = 0;
161 try {
162 begin();
163 if (!isOpen())
164 return 0;
165 thread = NativeThread.current();
166 do {
167 n = IOUtil.write(fd, src, -1, nd, lock);
168 } while ((n == IOStatus.INTERRUPTED) && isOpen());
169 return IOStatus.normalize(n);
170 } finally {
171 thread = 0;
172 end((n > 0) || (n == IOStatus.UNAVAILABLE));
173 assert IOStatus.check(n);
174 }
175 }
176 }
177
178 public long write(ByteBuffer[] srcs) throws IOException {
179 if (srcs == null)
180 throw new NullPointerException();
181 ensureOpen();
182 synchronized (lock) {
183 long n = 0;
184 try {
185 begin();
186 if (!isOpen())
187 return 0;
188 thread = NativeThread.current();
189 do {
190 n = IOUtil.write(fd, srcs, nd);
191 } while ((n == IOStatus.INTERRUPTED) && isOpen());
192 return IOStatus.normalize(n);
193 } finally {
194 thread = 0;
195 end((n > 0) || (n == IOStatus.UNAVAILABLE));
196 assert IOStatus.check(n);
197 }
198 }
199 }
200
201 public long write(ByteBuffer[] srcs, int offset, int length)
202 throws IOException
203 {
204 if ((offset < 0) || (length < 0) || (offset > srcs.length - length))
205 throw new IndexOutOfBoundsException();
206 return write(Util.subsequence(srcs, offset, length));
207 }
208
209 static {
210 Util.load();
211 nd = new FileDispatcher();
212 }
213
214}