001: /*
002: * Copyright (c) 2000 by Matt Welsh and The Regents of the University of
003: * California. All rights reserved.
004: *
005: * Permission to use, copy, modify, and distribute this software and its
006: * documentation for any purpose, without fee, and without written agreement is
007: * hereby granted, provided that the above copyright notice and the following
008: * two paragraphs appear in all copies of this software.
009: *
010: * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
011: * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
012: * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
013: * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
014: *
015: * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
016: * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
017: * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
018: * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
019: * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
020: *
021: * Author: Matt Welsh <mdw@cs.berkeley.edu>
022: *
023: */
024:
025: package seda.nbio;
026:
027: import java.util.Vector;
028:
029: /**
030: * SelectSetPollImpl is an implementation of SelectSet which
031: * uses the UNIX poll(2) system call.
032: *
033: * @see SelectSet
034: */
035: class SelectSetPollImpl extends SelectSetImpl {
036: private Vector vec;
037: private SelectItem itemarr[];
038: private boolean needUpdate = false;
039: private int cachedActiveCount = -1;
040:
041: private native int doSelect(int timeout);
042:
043: // Push the internal vector to itemarr.
044: private void itemarrupdate() {
045: if (vec.size() == 0) {
046: itemarr = null;
047: } else {
048: itemarr = new SelectItem[vec.size()];
049: vec.copyInto(itemarr);
050: }
051: }
052:
053: /**
054: * Returns true if poll(2) is supported on this platform.
055: */
056: static boolean isSupported() {
057: return true;
058: }
059:
060: /**
061: * Create a SelectSetPollImpl with no SelectItems.
062: */
063: SelectSetPollImpl() {
064: vec = new Vector(1);
065: }
066:
067: /**
068: * Add a SelectItem to this SelectSetPollImpl.
069: */
070: synchronized void add(SelectItem sel) {
071: vec.addElement(sel);
072: needUpdate = true;
073: cachedActiveCount = -1;
074: }
075:
076: /**
077: * Add all of the SelectItems in the given array to the SelectSetPollImpl.
078: */
079: synchronized void add(SelectItem selarr[]) {
080: for (int i = 0; i < selarr.length; i++) {
081: vec.addElement(selarr[i]);
082: }
083: needUpdate = true;
084: cachedActiveCount = -1;
085: }
086:
087: /**
088: * Remove a SelectItem from the SelectSetPollImpl.
089: */
090: synchronized void remove(SelectItem sel) {
091: vec.removeElement(sel);
092: needUpdate = true;
093: cachedActiveCount = -1;
094: }
095:
096: /**
097: * Remove all of the SelectItems in the given array from the
098: * SelectSetPollImpl.
099: */
100: synchronized void remove(SelectItem selarr[]) {
101: for (int i = 0; i < selarr.length; i++) {
102: vec.removeElement(selarr[i]);
103: }
104: needUpdate = true;
105: cachedActiveCount = -1;
106: }
107:
108: /**
109: * Remove the SelectItem at the given index from the SelectSetPollImpl.
110: */
111: synchronized void remove(int index) {
112: vec.removeElementAt(index);
113: needUpdate = true;
114: cachedActiveCount = -1;
115: }
116:
117: /**
118: * Update any changed event masks in the SelectSet. Does nothing
119: * in this implementation.
120: */
121: void update() {
122: cachedActiveCount = -1;
123: }
124:
125: /**
126: * Update any changed event masks in this SelectItem. Does nothing
127: * in this implementation.
128: */
129: void update(SelectItem sel) {
130: cachedActiveCount = -1;
131: }
132:
133: /**
134: * Return the number of SelectItems in this SelectSetPollImpl.
135: */
136: synchronized int size() {
137: return vec.size();
138: }
139:
140: /**
141: * Return the number of active SelectItems in this SelectSetPollImpl.
142: */
143: synchronized int numActive() {
144: if (cachedActiveCount != -1)
145: return cachedActiveCount;
146: if (needUpdate) {
147: itemarrupdate();
148: needUpdate = false;
149: }
150: int count = 0;
151: if (itemarr != null) {
152: for (int i = 0; i < itemarr.length; i++) {
153: if (itemarr[i].events != 0)
154: count++;
155: }
156: }
157: cachedActiveCount = count;
158: return count;
159: }
160:
161: /**
162: * Return the SelectItem at the given index.
163: */
164: synchronized SelectItem elementAt(int index) {
165: return (SelectItem) vec.elementAt(index);
166: }
167:
168: /**
169: * Wait for events to occur on the SelectItems in this SelectSetPollImpl.
170: * Upon return, the 'revents' field of each SelectItem will be
171: * set to the mask of events that occurred. Note that this method
172: * <b>does not</b> set revents to 0 when called; after processing an
173: * event, it is the application's responsibility to clear the revents
174: * field. This is intentional: if the application wishes to delay
175: * the processing of an event, it can leave the revents field as-is so
176: * that subsequent calls to select will continue to indicate that the
177: * event is pending.
178: *
179: * <p>
180: * <b>IMPORTANT NOTE:</b> If timeout is non-zero, this call will
181: * <b>block</b> the thread which invokes it. If you are using
182: * Green Threads, this will block the entire JVM. Unless you have
183: * a single-threaded application, you should only use
184: * SelectSet.select() with native threads.
185: *
186: * @param timeout The maximum number of milliseconds to block waiting
187: * for an event to occur. A timeout of 0 means than select should not block;
188: * a timeout of -1 means that select should block indefinitely.
189: *
190: * @return The number of events received, or 0 if no events occurred.
191: */
192: int select(int timeout) {
193: synchronized (this ) {
194: if (needUpdate) {
195: itemarrupdate();
196: needUpdate = false;
197: }
198: }
199: return doSelect(timeout);
200: }
201:
202: /**
203: * Returns an array of SelectItems for which events matching the given
204: * event mask have occurred (that is, that the revents field matches
205: * the given mask).
206: *
207: * This is a convenience method and is not meant to be optimized; since
208: * it scans the SelectItem array and creates a new reference array, it
209: * imposes higher overhead than the application scanning the SelectItem
210: * array directly, using the size() and elementAt() methods.
211: */
212: synchronized SelectItem[] getEvents(short mask) {
213: int count = 0;
214: if (itemarr == null)
215: return null;
216: for (int i = 0; i < itemarr.length; i++) {
217: if (itemarr[i] == null) {
218: // XXX MDW Trying to nail a Heisenbug here
219: System.err
220: .println("SelectSetPollImpl warning: itemarr["
221: + i
222: + "] is null! Please report to mdw@cs.berkeley.edu.");
223: continue;
224: }
225: if ((itemarr[i].revents & mask) != 0)
226: count++;
227: }
228: if (count == 0)
229: return null;
230: SelectItem retarr[] = new SelectItem[count];
231: count = 0;
232: for (int i = 0; i < itemarr.length; i++) {
233: if (itemarr[i] == null) {
234: // XXX MDW Trying to nail a Heisenbug here
235: continue;
236: }
237: if ((itemarr[i].revents & mask) != 0) {
238: retarr[count] = itemarr[i];
239: count++;
240: }
241: }
242: return retarr;
243: }
244:
245: /**
246: * Returns an array of SelectItems for which some events have occurred
247: * (that is, that the revents field is nonzero).
248: *
249: * This is a convenience method and is not meant to be optimized; since
250: * it scans the SelectItem array and creates a new reference array, it
251: * imposes higher overhead than the application scanning the SelectItem
252: * array directly, using the size() and elementAt() methods.
253: */
254: synchronized SelectItem[] getEvents() {
255: return getEvents((short) 0xffff);
256: }
257:
258: public String toString() {
259: String s = "SelectSetPollImpl:\n";
260: for (int i = 0; i < size(); i++) {
261: s = s + "\t" + elementAt(i).toString() + "\n";
262: }
263: return s;
264: }
265:
266: }
|