Copyright (C) 2009-2013 Barchart, Inc. All rights reserved. Licensed under the OSI BSD License. http://www.opensource.org/licenses/bsd-license.php
/** * Copyright (C) 2009-2013 Barchart, Inc. <http://www.barchart.com/> * * All rights reserved. Licensed under the OSI BSD License. * * http://www.opensource.org/licenses/bsd-license.php */
package com.barchart.udt; import org.slf4j.Logger; import org.slf4j.LoggerFactory;
UDT Epoll Manager
See Also:
/** * UDT Epoll Manager * * @see <a href="http://en.wikipedia.org/wiki/Epoll">Epoll</a> * @see <a href="http://udt.sourceforge.net/udt4/doc/epoll.htm">UDT Epoll</a> */
public class EpollUDT {
poll interest option mask

see udt.h enum - EPOLLOpt

   UDT_EPOLL_IN = 0x1,
   UDT_EPOLL_OUT = 0x4,
   UDT_EPOLL_ERR = 0x8
this is subset adapted to jdk select pattern
/** * poll interest option mask * <p> * see udt.h enum - EPOLLOpt * * <pre> * UDT_EPOLL_IN = 0x1, * UDT_EPOLL_OUT = 0x4, * UDT_EPOLL_ERR = 0x8 * </pre> * * this is subset adapted to jdk select pattern */
public static enum Opt {
not interested
/** * not interested */
NONE(0x0), //
UDT_EPOLL_IN : interested in read
/** * UDT_EPOLL_IN : interested in read */
READ(0x1), //
UDT_EPOLL_OUT: interested in write
/** * UDT_EPOLL_OUT: interested in write */
WRITE(0x4), //
UDT_EPOLL_ERR: interested in exceptions
/** * UDT_EPOLL_ERR: interested in exceptions */
ERROR(0x8), // BOTH(WRITE.code | READ.code), // ERROR_READ(ERROR.code | READ.code), // ERROR_WRITE(ERROR.code | WRITE.code), // ALL(ERROR.code | WRITE.code | READ.code), // UNKNOWN(-1); ; private static final Opt[] ENUM_VALS = Opt.values(); public static Opt from(final int code) { for (final Opt known : ENUM_VALS) { if (known.code == code) { return known; } } return UNKNOWN; }
poll event mask;

used for both requesting interest and reporting readiness

/** * poll event mask; * <p> * used for both requesting interest and reporting readiness */
public final int code; Opt(final int code) { this.code = code; } public boolean hasError() { return (code & ERROR.code) != 0; } public boolean hasRead() { return (code & READ.code) != 0; } public boolean hasWrite() { return (code & WRITE.code) != 0; }
Non-empty mask of 3 parts.
/** * Non-empty mask of 3 parts. */
public boolean isValidInterestRequest() { switch (this) { case NONE: case READ: case WRITE: case ERROR: case BOTH: case ERROR_WRITE: case ERROR_READ: case ALL: return true; default: return false; } } } protected static final Logger log = LoggerFactory.getLogger(EpollUDT.class); protected final int id; protected volatile boolean isActive;
place holder socket to work around logic in epoll.h CEPoll::wait() which expects at least one socket being monitored with non empty interest
/** * place holder socket to work around logic in epoll.h CEPoll::wait() which * expects at least one socket being monitored with non empty interest */
private final SocketUDT socketUDT;
allocate poll
/** * allocate poll */
public EpollUDT() throws ExceptionUDT { id = SocketUDT.epollCreate0(); isActive = true; socketUDT = new SocketUDT(TypeUDT.DATAGRAM); SocketUDT.epollAdd0(id, socketUDT.id(), Opt.BOTH.code); log.debug("ep {} create", id()); }
deallocate poll; called on finalize()
/** * deallocate poll; called on {@link #finalize()} */
public void destroy() throws ExceptionUDT { SocketUDT.epollRemove0(id(), socketUDT.id()); socketUDT.close(); isActive = false; SocketUDT.epollRelease0(id()); log.debug("ep {} delete", id()); }
poll descriptor id
/** * poll descriptor id */
public int id() { return id; }
poll becomes active after instance creation and inactive after destroy()
/** * poll becomes active after instance creation and inactive after * {@link #destroy()} */
public boolean isActive() { return isActive; }
deallocate poll

NOTE: catch all exceptions; else prevents GC

NOTE: do not leak "this" references; else prevents GC

/** * deallocate poll * <p> * NOTE: catch all exceptions; else prevents GC * <p> * NOTE: do not leak "this" references; else prevents GC */
@Override protected void finalize() { try { destroy(); super.finalize(); } catch (final Throwable e) { log.error("failed to destroy id=" + id(), e); } }
register socket into event processing poll
/** * register socket into event processing poll */
public void add(final SocketUDT socket, final Opt option) throws ExceptionUDT { log.debug("ep {} add {} {}", id(), socket, option); // assert option.isValidInterestRequest(); SocketUDT.epollAdd0(id(), socket.id(), option.code); }
unregister socket from event processing poll
/** * unregister socket from event processing poll */
public void remove(final SocketUDT socket) throws ExceptionUDT { log.debug("ep {} rem {}", id(), socket); SocketUDT.epollRemove0(id(), socket.id()); }
update existing poll/socket registration with changed interest
/** * update existing poll/socket registration with changed interest */
public void update(final SocketUDT socket, final Opt option) throws ExceptionUDT { log.debug("ep {} mod {} {}", id(), socket, option); assert option.isValidInterestRequest(); SocketUDT.epollUpdate0(id(), socket.id(), option.code); }
report current poll/socket readiness
/** report current poll/socket readiness */
public Opt verify(final SocketUDT socket) throws ExceptionUDT { final int code = SocketUDT.epollVerify0(id(), socket.id()); return Opt.from(code); } }