home *** CD-ROM | disk | FTP | other *** search
/ Programming Languages Suite / JBuilder8.iso / Solaris / resource / jre / demo / jni / Poller / Poller.java < prev    next >
Encoding:
Java Source  |  2002-09-06  |  9.7 KB  |  304 lines

  1. /*
  2.  * @(#)Poller.java    1.5 01/12/03
  3.  *
  4.  * Copyright 2002 Sun Microsystems, Inc. All rights reserved.
  5.  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6.  */
  7.  
  8. import java.lang.reflect.*;
  9. import java.io.*;
  10. import java.net.*;
  11.  
  12. /**
  13.  * This class is provided for access to the underlying poll(2)
  14.  * or /dev/poll kernel interfaces.  This may be needed for
  15.  * multiplexing IO when an application cannot afford to have
  16.  * a thread block on each outstanding IO request.
  17.  *
  18.  * It currently supports the same basic functionality as the
  19.  * C poll(2) API, although for efficiency we needed to avoid
  20.  * passing the entire pollfd array for every call.  See man
  21.  * pages for poll(2) for info on C API and event types.
  22.  *
  23.  *
  24.  * @version 1.5, 12/03/01
  25.  * @author  Bruce Chapman
  26.  * @see     java.io.FileDescriptor
  27.  * @see     java.net.Socket
  28.  * @see     attached README.txt
  29.  * @since   JDK1.2
  30.  */
  31.  
  32. public class Poller {
  33.   /**
  34.    * Solaris POLL event types.
  35.    */
  36.   public final static short POLLERR  = 0x08;
  37.   public final static short POLLHUP  = 0x10;
  38.   public final static short POLLNVAL = 0x20;
  39.   public final static short POLLIN   = 1;
  40.   public final static short POLLPRI  = 2;
  41.   public final static short POLLOUT  = 4;
  42.   public final static short POLLRDNORM = 0x40;
  43.   public final static short POLLWRNORM = POLLOUT ;
  44.   public final static short POLLRDBAND = 0x80;
  45.   public final static short POLLWRBAND = 0x100;
  46.   public final static short POLLNORM   = POLLRDNORM;
  47.  
  48.   /*
  49.    * This global synchronization object must be used for all
  50.    * creation or destruction of Poller objects.
  51.    */
  52.   private final static Object globalSync = new Object();
  53.  
  54.   /*
  55.    * The handle for a Poller Object...is used in the JNI C code
  56.    * where all the associated data is kept.
  57.    */
  58.   private int handle;
  59.  
  60.   /**
  61.    * Constructs an instance of a <code>Poller</code> object.
  62.    * Native code uses sysconf(_SC_OPEN_MAX) to determine how
  63.    * many fd/skt objects this Poller object can contain.
  64.    */
  65.   public Poller() throws Exception { 
  66.     synchronized(globalSync) {
  67.       this.handle = nativeCreatePoller(-1);
  68.     }
  69.   }
  70.  
  71.   /**
  72.    * Constructs an instance of a <code>Poller</code> object.
  73.    * @param  maxFd the maximum number of FileDescriptors/Sockets
  74.    *         this Poller object can contain.
  75.    */
  76.   public Poller(int maxFd) throws Exception { 
  77.     synchronized(globalSync) {
  78.       this.handle = nativeCreatePoller(maxFd);
  79.     }
  80.   }
  81.  
  82.   /**
  83.    * Needed to clean up at the JNI C level when object is GCd.
  84.    */
  85.   protected void finalize() throws Throwable {
  86.     synchronized(globalSync) {
  87.       nativeDestroyPoller(handle);
  88.       super.finalize();
  89.     }
  90.   }
  91.  
  92.   /**
  93.    * Since we can't guarantee WHEN finalize is called, we may
  94.    * recycle on our own.
  95.    * @param  maxFd the maximum number of FileDescriptors/Sockets
  96.    *         this Poller object can contain.
  97.    */
  98.   public void reset(int maxFd) throws Exception { 
  99.     synchronized(globalSync) {
  100.       nativeDestroyPoller(handle);
  101.       this.handle = nativeCreatePoller(maxFd);
  102.     }
  103.   }
  104.   /**
  105.    * Since we can't guarantee WHEN finalize is called, we may
  106.    * recycle on our own.
  107.    */
  108.   public void reset() throws Exception { 
  109.     synchronized(globalSync) {
  110.       nativeDestroyPoller(handle);
  111.       this.handle = nativeCreatePoller(-1);
  112.     }
  113.   }
  114.  
  115.   /**
  116.    * Add FileDescriptor to the set handled by this Poller object.
  117.    *
  118.    * @param  fdObj the FileDescriptor, Socket, or ServerSocket to add.
  119.    * @param  event the bitmask of events we are interested in.
  120.    * @return the OS level fd associated with this IO Object
  121.    *          (which is what waitMultiple() stores in fds[])
  122.    */
  123.   public synchronized int add(Object fdObj, short event) throws Exception {
  124.     return nativeAddFd(handle,findfd(fdObj), event);
  125.   }
  126.  
  127.   /**
  128.    * Remove FileDescriptor from the set handled by this Poller object.
  129.    *
  130.    * Must be called before the fd/skt is closed.
  131.    * @param fdObj the FileDescriptor, Socket, or ServerSocket to remove.
  132.    * @return true if removal succeeded.
  133.    */
  134.   public synchronized boolean remove(Object fdObj) throws Exception {
  135.     return (nativeRemoveFd(handle,findfd(fdObj)) == 1);
  136.   }
  137.   /**
  138.    * Check if fd or socket is already in the set handled by this Poller object
  139.    *
  140.    * @param fdObj the FileDescriptor or [Server]Socket to check.
  141.    * @return true if fd/skt is in the set for this Poller object.
  142.    */
  143.   public synchronized boolean isMember(Object fdObj) throws Exception {
  144.     return (nativeIsMember(handle,findfd(fdObj)) == 1);
  145.   }
  146.   /**
  147.    * Wait on Multiple IO Objects.
  148.    * 
  149.    * @param maxRet    the maximum number of fds[] and revents[] to return.
  150.    * @param fds[]     (return) an array of ints in which to store fds with
  151.    *                  available data upon a successful non-timeout return.
  152.    *                  fds.length must be >= maxRet
  153.    * @param revents[] (return) the actual events available on the
  154.    *                  same-indexed fds[] (i.e. fds[0] has events revents[0])
  155.    *                  revents.length must be >= maxRet
  156.    *
  157.    * Note : both above arrays are "dense," i.e. only fds[] with events
  158.    *        available are returned.
  159.    *
  160.    * @param timeout   the maximum number of milliseconds to wait for
  161.    *                  events before timing out.
  162.    * @return          the number of fds with triggered events.
  163.    *
  164.    * Note : convenience methods exist for skipping the timeout parameter
  165.    *        or the maxRet parameter (in the case of no maxRet, fds.length
  166.    *        must equal revents.length)
  167.    *
  168.    * obj.waitMultiple(null,null,timeout) can be used for pausing the LWP
  169.    * (much more reliable and scalable than Thread.sleep() or Object.wait())
  170.    */
  171.   public synchronized int waitMultiple(int maxRet, int[] fds,short[] revents,
  172.                        long timeout) throws Exception
  173.     {
  174.       if ((revents == null) || (fds == null)) {
  175.     if (maxRet > 0) {
  176.       throw new NullPointerException("fds or revents is null");
  177.     }
  178.       } else if ( (maxRet < 0) ||
  179.           (maxRet > revents.length) || (maxRet > fds.length) ) {
  180.     throw new IllegalArgumentException("maxRet out of range");
  181.       }
  182.  
  183.       int ret = nativeWait(handle, maxRet, fds, revents, timeout);
  184.       if (ret < 0) {
  185.     throw new InterruptedIOException();
  186.       }
  187.       return ret;
  188.     }
  189.  
  190.   /**
  191.    * Wait on Multiple IO Objects (no timeout).
  192.    * A convenience method for waiting indefinitely on IO events
  193.    *
  194.    * @see Poller#waitMultiple
  195.    *
  196.    */
  197.   public int waitMultiple(int maxRet, int[] fds, short[] revents)
  198.     throws Exception
  199.     {
  200.       return waitMultiple(maxRet, fds, revents,-1L); // already synchronized
  201.     }
  202.  
  203.   /**
  204.    * Wait on Multiple IO Objects (no maxRet).
  205.    * A convenience method for waiting on IO events when the fds
  206.    * and revents arrays are the same length and that specifies the
  207.    * maximum number of return events.
  208.    *
  209.    * @see Poller#waitMultiple
  210.    * 
  211.    */
  212.   public synchronized int waitMultiple(int[] fds, short[] revents,
  213.                        long timeout) throws Exception
  214.     {
  215.       if ((revents == null) && (fds == null)) {
  216.     return nativeWait(handle,0,null,null,timeout);
  217.       } else if ((revents == null) || (fds == null)) {
  218.     throw new NullPointerException("revents or fds is null");
  219.       } else if (fds.length == revents.length) {
  220.     return nativeWait(handle, fds.length, fds, revents, timeout);
  221.       }
  222.       throw new IllegalArgumentException("fds.length != revents.length");
  223.     }
  224.  
  225.  
  226.   /**
  227.    * Wait on Multiple IO Objects (no maxRet/timeout).
  228.    * A convenience method for waiting on IO events when the fds
  229.    * and revents arrays are the same length and that specifies the
  230.    * maximum number of return events, and when waiting indefinitely
  231.    * for IO events to occur.
  232.    *
  233.    * @see Poller#waitMultiple
  234.    *
  235.    */
  236.   public int waitMultiple(int[] fds, short[] revents)
  237.     throws Exception
  238.     {
  239.       if ((revents == null) || (fds == null)) {
  240.     throw new NullPointerException("fds or revents is null");
  241.       } else if (fds.length == revents.length) {
  242.     return waitMultiple(revents.length,fds,revents,-1L); // already sync
  243.       }
  244.       throw new IllegalArgumentException("fds.length != revents.length");
  245.     }
  246.  
  247.   // Utility - get (int) fd from FileDescriptor or [Server]Socket objects.
  248.  
  249.   private int findfd(Object fdObj) throws Exception {
  250.     Class cl;
  251.     Field f;
  252.     Object val, implVal;
  253.     
  254.     if ((fdObj instanceof java.net.Socket) ||
  255.     (fdObj instanceof java.net.ServerSocket)) {
  256.       cl = fdObj.getClass();
  257.       f = cl.getDeclaredField("impl");
  258.       f.setAccessible(true);
  259.       val = f.get(fdObj);
  260.       cl = f.getType();
  261.       f = cl.getDeclaredField("fd");
  262.       f.setAccessible(true);
  263.       implVal = f.get(val);
  264.       cl = f.getType();
  265.       f = cl.getDeclaredField("fd");
  266.       f.setAccessible(true);
  267.       return  ((Integer) f.get(implVal)).intValue();
  268.     } else if ( fdObj instanceof java.io.FileDescriptor ) {
  269.       cl = fdObj.getClass();
  270.       f = cl.getDeclaredField("fd");
  271.       f.setAccessible(true);
  272.       return  ((Integer) f.get(fdObj)).intValue();
  273.     }
  274.     else {
  275.       throw new IllegalArgumentException("Illegal Object type.");
  276.     }
  277.   }
  278.  
  279.   // Actual NATIVE calls
  280.  
  281.   private static native int  nativeInit();
  282.   private native int  nativeCreatePoller(int maxFd) throws Exception;
  283.   private native void nativeDestroyPoller(int handle) throws Exception;
  284.   private native int  nativeAddFd(int handle, int fd, short events)
  285.     throws Exception;
  286.   private native int  nativeRemoveFd(int handle, int fd) throws Exception;
  287.   private native int  nativeRemoveIndex(int handle, int index)
  288.     throws Exception;
  289.   private native int  nativeIsMember(int handle, int fd) throws Exception;
  290.   private native int  nativeWait(int handle, int maxRet, int[] fds,
  291.                     short[] events, long timeout)
  292.     throws Exception;
  293.   /**
  294.    * Get number of active CPUs in this machine
  295.    * to determine proper level of concurrency.
  296.    */ 
  297.   public static native int  getNumCPUs();
  298.  
  299.   static {
  300.       System.loadLibrary("poller");
  301.       nativeInit();
  302.   }
  303. }
  304.