/* * JacORB - a free Java ORB * * Copyright (C) 2012 Gerald Brose / The JacORB Team. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ package org.jacorb.util; import java.nio.channels.SelectionKey; import java.nio.channels.SocketChannel; /** * defines a single request to be registered with the selector. * this can be a timed event, I/O event, or I/O event with an * expiration. * @author Ciju John {@literal <johnc@ociweb.com>}} */ public class SelectorRequest { /** * the types of events to be waited for. */ public enum Type { CONNECT, ACCEPT, READ, WRITE, TIMER } /** * the current status of the request. */ public enum Status { PENDING, ASSIGNED, READY, EXPIRED, FAILED, IOERROR, FINISHED, SHUTDOWN, CLOSED } public final Type type; public Status status = null; public final SocketChannel channel; public SelectionKey key = null; public final int op; public SelectorRequestCallback callback; public final long nanoDeadline; // private final ReentrantLock lock = new ReentrantLock(); private final Object lock = new Object(); /** * Constructs a new SelectorRequest for an I/O event * @param type is the kind of event to wait for * @param channel is the I/O on which the event is expected * @param callback is the object to be notified when the event occurs * @param nanoDeadline is an expiration time. It is an absolute time based upon System.nanoTime(). * A deadline of '0' is used for no deadline. */ public SelectorRequest (Type type, SocketChannel channel, SelectorRequestCallback callback, long nanoDeadline) { this.type = type; switch (type) { case CONNECT: op = SelectionKey.OP_CONNECT; break; case READ: op = SelectionKey.OP_READ; break; case WRITE: op = SelectionKey.OP_WRITE; break; default: op = 0; } this.channel = channel; this.callback = callback; this.nanoDeadline = (nanoDeadline == 0 ? Long.MAX_VALUE : nanoDeadline); } /** * Constructs a new SelectorRequest for an timer event * @param callback is the object to be notified when the event occurs * @param nanoDeadline is an expiration time. It is an absolute time based upon System.nanoTime(). * A deadline of '0' is used for no deadline. */ public SelectorRequest (SelectorRequestCallback callback, long nanoDeadline) { type = Type.TIMER; op = 0; channel = null; this.callback = callback; this.nanoDeadline = (nanoDeadline == 0 ? Long.MAX_VALUE : nanoDeadline); } /** * Called by the SelectorManager to notify a change of status. Will wake up * a thread blocked in waitOnCOmpletion */ public void setStatus (Status status) { synchronized (lock) { this.status = status; // the below might just need to be notify() lock.notify(); } } /** * determines if the current status is one of the final statuses * @return false if the status is PENDING, ASSIGNED, or READY, true for all others */ public boolean isFinalized () { return status != null && status != Status.PENDING && status != Status.ASSIGNED && status != Status.READY; } /** * a blocking call to wait for a status change or a timeout. * @param nanoDeadline is an explicit timeout for waiting on a change * @return this requester's status after a notification or a timeout. */ public Status waitOnCompletion (long nanoDeadline) { long myNanoDeadline = (nanoDeadline == 0 ? Long.MAX_VALUE : nanoDeadline); synchronized (lock) { while (myNanoDeadline > System.nanoTime() && !isFinalized()) { long remaining = myNanoDeadline - System.nanoTime(); long millis = remaining / 1000000; int nanos = (int)(remaining - (millis * 1000000)); try { lock.wait (millis, nanos); } catch (InterruptedException e) { // ignored } catch (IllegalArgumentException ex) { // indicates we have run out of time if the value // of timeout is negative or the value of nanos is // not in the range 0-999999. break; } } } return status; } }