alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Java example source code file (Poller.java)

This example Java source code file (Poller.java) is included in the alvinalexander.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Learn more about this Java project at its project page.

Java - Java tags/keywords

class, exception, illegalargumentexception, integer, interruptedioexception, net, network, nullpointerexception, object, poller, pollin, pollnorm, pollout, pollrdnorm, pollwrband, reflection, throwable

The Poller.java Java example source code

/*
 * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Oracle nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

/*
 * This source code is provided to illustrate the usage of a given feature
 * or technique and has been deliberately simplified. Additional steps
 * required for a production-quality application, such as security checks,
 * input validation and proper error handling, might not be present in
 * this sample code.
 */


import java.lang.reflect.*;
import java.io.*;
import java.net.*;

/**
 * This class is provided for access to the underlying poll(2)
 * or /dev/poll kernel interfaces.  This may be needed for
 * multiplexing IO when an application cannot afford to have
 * a thread block on each outstanding IO request.
 *
 * It currently supports the same basic functionality as the
 * C poll(2) API, although for efficiency we needed to avoid
 * passing the entire pollfd array for every call.  See man
 * pages for poll(2) for info on C API and event types.
 *
 *
 * @author  Bruce Chapman
 * @see     java.io.FileDescriptor
 * @see     java.net.Socket
 * @see     attached README.txt
 * @since   JDK1.2
 */

public class Poller {
  /**
   * Solaris POLL event types.
   */
  public final static short POLLERR  = 0x08;
  public final static short POLLHUP  = 0x10;
  public final static short POLLNVAL = 0x20;
  public final static short POLLIN   = 1;
  public final static short POLLPRI  = 2;
  public final static short POLLOUT  = 4;
  public final static short POLLRDNORM = 0x40;
  public final static short POLLWRNORM = POLLOUT ;
  public final static short POLLRDBAND = 0x80;
  public final static short POLLWRBAND = 0x100;
  public final static short POLLNORM   = POLLRDNORM;

  /*
   * This global synchronization object must be used for all
   * creation or destruction of Poller objects.
   */
  private final static Object globalSync = new Object();

  /*
   * The handle for a Poller Object...is used in the JNI C code
   * where all the associated data is kept.
   */
  private int handle;

  /**
   * Constructs an instance of a <code>Poller object.
   * Native code uses sysconf(_SC_OPEN_MAX) to determine how
   * many fd/skt objects this Poller object can contain.
   */
  public Poller() throws Exception {
    synchronized(globalSync) {
      this.handle = nativeCreatePoller(-1);
    }
  }

  /**
   * Constructs an instance of a <code>Poller object.
   * @param  maxFd the maximum number of FileDescriptors/Sockets
   *         this Poller object can contain.
   */
  public Poller(int maxFd) throws Exception {
    synchronized(globalSync) {
      this.handle = nativeCreatePoller(maxFd);
    }
  }

  /**
   * Needed to clean up at the JNI C level when object is GCd.
   */
  protected void finalize() throws Throwable {
    synchronized(globalSync) {
      nativeDestroyPoller(handle);
      super.finalize();
    }
  }

  /**
   * Since we can't guarantee WHEN finalize is called, we may
   * recycle on our own.
   * @param  maxFd the maximum number of FileDescriptors/Sockets
   *         this Poller object can contain.
   */
  public void reset(int maxFd) throws Exception {
    synchronized(globalSync) {
      nativeDestroyPoller(handle);
      this.handle = nativeCreatePoller(maxFd);
    }
  }
  /**
   * Since we can't guarantee WHEN finalize is called, we may
   * recycle on our own.
   */
  public void reset() throws Exception {
    synchronized(globalSync) {
      nativeDestroyPoller(handle);
      this.handle = nativeCreatePoller(-1);
    }
  }

  /**
   * Add FileDescriptor to the set handled by this Poller object.
   *
   * @param  fdObj the FileDescriptor, Socket, or ServerSocket to add.
   * @param  event the bitmask of events we are interested in.
   * @return the OS level fd associated with this IO Object
   *          (which is what waitMultiple() stores in fds[])
   */
  public synchronized int add(Object fdObj, short event) throws Exception {
    return nativeAddFd(handle,findfd(fdObj), event);
  }

  /**
   * Remove FileDescriptor from the set handled by this Poller object.
   *
   * Must be called before the fd/skt is closed.
   * @param fdObj the FileDescriptor, Socket, or ServerSocket to remove.
   * @return true if removal succeeded.
   */
  public synchronized boolean remove(Object fdObj) throws Exception {
    return (nativeRemoveFd(handle,findfd(fdObj)) == 1);
  }
  /**
   * Check if fd or socket is already in the set handled by this Poller object
   *
   * @param fdObj the FileDescriptor or [Server]Socket to check.
   * @return true if fd/skt is in the set for this Poller object.
   */
  public synchronized boolean isMember(Object fdObj) throws Exception {
    return (nativeIsMember(handle,findfd(fdObj)) == 1);
  }
  /**
   * Wait on Multiple IO Objects.
   *
   * @param maxRet    the maximum number of fds[] and revents[] to return.
   * @param fds[]     (return) an array of ints in which to store fds with
   *                  available data upon a successful non-timeout return.
   *                  fds.length must be >= maxRet
   * @param revents[] (return) the actual events available on the
   *                  same-indexed fds[] (i.e. fds[0] has events revents[0])
   *                  revents.length must be >= maxRet
   *
   * Note : both above arrays are "dense," i.e. only fds[] with events
   *        available are returned.
   *
   * @param timeout   the maximum number of milliseconds to wait for
   *                  events before timing out.
   * @return          the number of fds with triggered events.
   *
   * Note : convenience methods exist for skipping the timeout parameter
   *        or the maxRet parameter (in the case of no maxRet, fds.length
   *        must equal revents.length)
   *
   * obj.waitMultiple(null,null,timeout) can be used for pausing the LWP
   * (much more reliable and scalable than Thread.sleep() or Object.wait())
   */
  public synchronized int waitMultiple(int maxRet, int[] fds,short[] revents,
                                       long timeout) throws Exception
    {
      if ((revents == null) || (fds == null)) {
        if (maxRet > 0) {
          throw new NullPointerException("fds or revents is null");
        }
      } else if ( (maxRet < 0) ||
                  (maxRet > revents.length) || (maxRet > fds.length) ) {
        throw new IllegalArgumentException("maxRet out of range");
      }

      int ret = nativeWait(handle, maxRet, fds, revents, timeout);
      if (ret < 0) {
        throw new InterruptedIOException();
      }
      return ret;
    }

  /**
   * Wait on Multiple IO Objects (no timeout).
   * A convenience method for waiting indefinitely on IO events
   *
   * @see Poller#waitMultiple
   *
   */
  public int waitMultiple(int maxRet, int[] fds, short[] revents)
    throws Exception
    {
      return waitMultiple(maxRet, fds, revents,-1L); // already synchronized
    }

  /**
   * Wait on Multiple IO Objects (no maxRet).
   * A convenience method for waiting on IO events when the fds
   * and revents arrays are the same length and that specifies the
   * maximum number of return events.
   *
   * @see Poller#waitMultiple
   *
   */
  public synchronized int waitMultiple(int[] fds, short[] revents,
                                       long timeout) throws Exception
    {
      if ((revents == null) && (fds == null)) {
        return nativeWait(handle,0,null,null,timeout);
      } else if ((revents == null) || (fds == null)) {
        throw new NullPointerException("revents or fds is null");
      } else if (fds.length == revents.length) {
        return nativeWait(handle, fds.length, fds, revents, timeout);
      }
      throw new IllegalArgumentException("fds.length != revents.length");
    }


  /**
   * Wait on Multiple IO Objects (no maxRet/timeout).
   * A convenience method for waiting on IO events when the fds
   * and revents arrays are the same length and that specifies the
   * maximum number of return events, and when waiting indefinitely
   * for IO events to occur.
   *
   * @see Poller#waitMultiple
   *
   */
  public int waitMultiple(int[] fds, short[] revents)
    throws Exception
    {
      if ((revents == null) || (fds == null)) {
        throw new NullPointerException("fds or revents is null");
      } else if (fds.length == revents.length) {
        return waitMultiple(revents.length,fds,revents,-1L); // already sync
      }
      throw new IllegalArgumentException("fds.length != revents.length");
    }

  // Utility - get (int) fd from FileDescriptor or [Server]Socket objects.

  private int findfd(Object fdObj) throws Exception {
    Class cl;
    Field f;
    Object val, implVal;

    if ((fdObj instanceof java.net.Socket) ||
        (fdObj instanceof java.net.ServerSocket)) {
      cl = fdObj.getClass();
      f = cl.getDeclaredField("impl");
      f.setAccessible(true);
      val = f.get(fdObj);
      cl = f.getType();
      f = cl.getDeclaredField("fd");
      f.setAccessible(true);
      implVal = f.get(val);
      cl = f.getType();
      f = cl.getDeclaredField("fd");
      f.setAccessible(true);
      return  ((Integer) f.get(implVal)).intValue();
    } else if ( fdObj instanceof java.io.FileDescriptor ) {
      cl = fdObj.getClass();
      f = cl.getDeclaredField("fd");
      f.setAccessible(true);
      return  ((Integer) f.get(fdObj)).intValue();
    }
    else {
      throw new IllegalArgumentException("Illegal Object type.");
    }
  }

  // Actual NATIVE calls

  private static native int  nativeInit();
  private native int  nativeCreatePoller(int maxFd) throws Exception;
  private native void nativeDestroyPoller(int handle) throws Exception;
  private native int  nativeAddFd(int handle, int fd, short events)
    throws Exception;
  private native int  nativeRemoveFd(int handle, int fd) throws Exception;
  private native int  nativeRemoveIndex(int handle, int index)
    throws Exception;
  private native int  nativeIsMember(int handle, int fd) throws Exception;
  private native int  nativeWait(int handle, int maxRet, int[] fds,
                                        short[] events, long timeout)
    throws Exception;
  /**
   * Get number of active CPUs in this machine
   * to determine proper level of concurrency.
   */
  public static native int  getNumCPUs();

  static {
      System.loadLibrary("poller");
      nativeInit();
  }
}

Other Java examples (source code examples)

Here is a short list of links related to this Java Poller.java source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.