Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/solaris/demo/jni/Poller/Poller.java
32287 views
/*1* Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.2*3* Redistribution and use in source and binary forms, with or without4* modification, are permitted provided that the following conditions5* are met:6*7* - Redistributions of source code must retain the above copyright8* notice, this list of conditions and the following disclaimer.9*10* - Redistributions in binary form must reproduce the above copyright11* notice, this list of conditions and the following disclaimer in the12* documentation and/or other materials provided with the distribution.13*14* - Neither the name of Oracle nor the names of its15* contributors may be used to endorse or promote products derived16* from this software without specific prior written permission.17*18* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS19* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,20* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR21* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR22* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,23* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,24* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR25* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF26* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING27* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS28* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.29*/3031/*32* This source code is provided to illustrate the usage of a given feature33* or technique and has been deliberately simplified. Additional steps34* required for a production-quality application, such as security checks,35* input validation and proper error handling, might not be present in36* this sample code.37*/383940import java.lang.reflect.*;41import java.io.*;42import java.net.*;4344/**45* This class is provided for access to the underlying poll(2)46* or /dev/poll kernel interfaces. This may be needed for47* multiplexing IO when an application cannot afford to have48* a thread block on each outstanding IO request.49*50* It currently supports the same basic functionality as the51* C poll(2) API, although for efficiency we needed to avoid52* passing the entire pollfd array for every call. See man53* pages for poll(2) for info on C API and event types.54*55*56* @author Bruce Chapman57* @see java.io.FileDescriptor58* @see java.net.Socket59* @see attached README.txt60* @since JDK1.261*/6263public class Poller {64/**65* Solaris POLL event types.66*/67public final static short POLLERR = 0x08;68public final static short POLLHUP = 0x10;69public final static short POLLNVAL = 0x20;70public final static short POLLIN = 1;71public final static short POLLPRI = 2;72public final static short POLLOUT = 4;73public final static short POLLRDNORM = 0x40;74public final static short POLLWRNORM = POLLOUT ;75public final static short POLLRDBAND = 0x80;76public final static short POLLWRBAND = 0x100;77public final static short POLLNORM = POLLRDNORM;7879/*80* This global synchronization object must be used for all81* creation or destruction of Poller objects.82*/83private final static Object globalSync = new Object();8485/*86* The handle for a Poller Object...is used in the JNI C code87* where all the associated data is kept.88*/89private int handle;9091/**92* Constructs an instance of a <code>Poller</code> object.93* Native code uses sysconf(_SC_OPEN_MAX) to determine how94* many fd/skt objects this Poller object can contain.95*/96public Poller() throws Exception {97synchronized(globalSync) {98this.handle = nativeCreatePoller(-1);99}100}101102/**103* Constructs an instance of a <code>Poller</code> object.104* @param maxFd the maximum number of FileDescriptors/Sockets105* this Poller object can contain.106*/107public Poller(int maxFd) throws Exception {108synchronized(globalSync) {109this.handle = nativeCreatePoller(maxFd);110}111}112113/**114* Needed to clean up at the JNI C level when object is GCd.115*/116protected void finalize() throws Throwable {117synchronized(globalSync) {118nativeDestroyPoller(handle);119super.finalize();120}121}122123/**124* Since we can't guarantee WHEN finalize is called, we may125* recycle on our own.126* @param maxFd the maximum number of FileDescriptors/Sockets127* this Poller object can contain.128*/129public void reset(int maxFd) throws Exception {130synchronized(globalSync) {131nativeDestroyPoller(handle);132this.handle = nativeCreatePoller(maxFd);133}134}135/**136* Since we can't guarantee WHEN finalize is called, we may137* recycle on our own.138*/139public void reset() throws Exception {140synchronized(globalSync) {141nativeDestroyPoller(handle);142this.handle = nativeCreatePoller(-1);143}144}145146/**147* Add FileDescriptor to the set handled by this Poller object.148*149* @param fdObj the FileDescriptor, Socket, or ServerSocket to add.150* @param event the bitmask of events we are interested in.151* @return the OS level fd associated with this IO Object152* (which is what waitMultiple() stores in fds[])153*/154public synchronized int add(Object fdObj, short event) throws Exception {155return nativeAddFd(handle,findfd(fdObj), event);156}157158/**159* Remove FileDescriptor from the set handled by this Poller object.160*161* Must be called before the fd/skt is closed.162* @param fdObj the FileDescriptor, Socket, or ServerSocket to remove.163* @return true if removal succeeded.164*/165public synchronized boolean remove(Object fdObj) throws Exception {166return (nativeRemoveFd(handle,findfd(fdObj)) == 1);167}168/**169* Check if fd or socket is already in the set handled by this Poller object170*171* @param fdObj the FileDescriptor or [Server]Socket to check.172* @return true if fd/skt is in the set for this Poller object.173*/174public synchronized boolean isMember(Object fdObj) throws Exception {175return (nativeIsMember(handle,findfd(fdObj)) == 1);176}177/**178* Wait on Multiple IO Objects.179*180* @param maxRet the maximum number of fds[] and revents[] to return.181* @param fds[] (return) an array of ints in which to store fds with182* available data upon a successful non-timeout return.183* fds.length must be >= maxRet184* @param revents[] (return) the actual events available on the185* same-indexed fds[] (i.e. fds[0] has events revents[0])186* revents.length must be >= maxRet187*188* Note : both above arrays are "dense," i.e. only fds[] with events189* available are returned.190*191* @param timeout the maximum number of milliseconds to wait for192* events before timing out.193* @return the number of fds with triggered events.194*195* Note : convenience methods exist for skipping the timeout parameter196* or the maxRet parameter (in the case of no maxRet, fds.length197* must equal revents.length)198*199* obj.waitMultiple(null,null,timeout) can be used for pausing the LWP200* (much more reliable and scalable than Thread.sleep() or Object.wait())201*/202public synchronized int waitMultiple(int maxRet, int[] fds,short[] revents,203long timeout) throws Exception204{205if ((revents == null) || (fds == null)) {206if (maxRet > 0) {207throw new NullPointerException("fds or revents is null");208}209} else if ( (maxRet < 0) ||210(maxRet > revents.length) || (maxRet > fds.length) ) {211throw new IllegalArgumentException("maxRet out of range");212}213214int ret = nativeWait(handle, maxRet, fds, revents, timeout);215if (ret < 0) {216throw new InterruptedIOException();217}218return ret;219}220221/**222* Wait on Multiple IO Objects (no timeout).223* A convenience method for waiting indefinitely on IO events224*225* @see Poller#waitMultiple226*227*/228public int waitMultiple(int maxRet, int[] fds, short[] revents)229throws Exception230{231return waitMultiple(maxRet, fds, revents,-1L); // already synchronized232}233234/**235* Wait on Multiple IO Objects (no maxRet).236* A convenience method for waiting on IO events when the fds237* and revents arrays are the same length and that specifies the238* maximum number of return events.239*240* @see Poller#waitMultiple241*242*/243public synchronized int waitMultiple(int[] fds, short[] revents,244long timeout) throws Exception245{246if ((revents == null) && (fds == null)) {247return nativeWait(handle,0,null,null,timeout);248} else if ((revents == null) || (fds == null)) {249throw new NullPointerException("revents or fds is null");250} else if (fds.length == revents.length) {251return nativeWait(handle, fds.length, fds, revents, timeout);252}253throw new IllegalArgumentException("fds.length != revents.length");254}255256257/**258* Wait on Multiple IO Objects (no maxRet/timeout).259* A convenience method for waiting on IO events when the fds260* and revents arrays are the same length and that specifies the261* maximum number of return events, and when waiting indefinitely262* for IO events to occur.263*264* @see Poller#waitMultiple265*266*/267public int waitMultiple(int[] fds, short[] revents)268throws Exception269{270if ((revents == null) || (fds == null)) {271throw new NullPointerException("fds or revents is null");272} else if (fds.length == revents.length) {273return waitMultiple(revents.length,fds,revents,-1L); // already sync274}275throw new IllegalArgumentException("fds.length != revents.length");276}277278// Utility - get (int) fd from FileDescriptor or [Server]Socket objects.279280private int findfd(Object fdObj) throws Exception {281Class cl;282Field f;283Object val, implVal;284285if ((fdObj instanceof java.net.Socket) ||286(fdObj instanceof java.net.ServerSocket)) {287cl = fdObj.getClass();288f = cl.getDeclaredField("impl");289f.setAccessible(true);290val = f.get(fdObj);291cl = f.getType();292f = cl.getDeclaredField("fd");293f.setAccessible(true);294implVal = f.get(val);295cl = f.getType();296f = cl.getDeclaredField("fd");297f.setAccessible(true);298return ((Integer) f.get(implVal)).intValue();299} else if ( fdObj instanceof java.io.FileDescriptor ) {300cl = fdObj.getClass();301f = cl.getDeclaredField("fd");302f.setAccessible(true);303return ((Integer) f.get(fdObj)).intValue();304}305else {306throw new IllegalArgumentException("Illegal Object type.");307}308}309310// Actual NATIVE calls311312private static native int nativeInit();313private native int nativeCreatePoller(int maxFd) throws Exception;314private native void nativeDestroyPoller(int handle) throws Exception;315private native int nativeAddFd(int handle, int fd, short events)316throws Exception;317private native int nativeRemoveFd(int handle, int fd) throws Exception;318private native int nativeRemoveIndex(int handle, int index)319throws Exception;320private native int nativeIsMember(int handle, int fd) throws Exception;321private native int nativeWait(int handle, int maxRet, int[] fds,322short[] events, long timeout)323throws Exception;324/**325* Get number of active CPUs in this machine326* to determine proper level of concurrency.327*/328public static native int getNumCPUs();329330static {331System.loadLibrary("poller");332nativeInit();333}334}335336337