EPollArrayWrapper

class EPollArrayWrapper {
   64       // EPOLL_EVENTS
   65       static final int EPOLLIN      = 0x001;
   66   
   67       // opcodes
   68       static final int EPOLL_CTL_ADD      = 1;
   69       static final int EPOLL_CTL_DEL      = 2;
   70       static final int EPOLL_CTL_MOD      = 3;
   71   
   72       // Miscellaneous constants
   73       static final int SIZE_EPOLLEVENT  = sizeofEPollEvent();
   74       static final int EVENT_OFFSET     = 0;
   75       static final int DATA_OFFSET      = offsetofData();
   76       static final int FD_OFFSET        = DATA_OFFSET;
   77       static final int NUM_EPOLLEVENTS  = Math.min(fdLimit(), 8192);
   78   
   79       // Base address of the native pollArray
   80       private final long pollArrayAddress;
   81   
   82       // Set of "idle" channels
   83       private final HashSet<SelChImpl> idleSet;
   84   
   85       EPollArrayWrapper() {
   86           // creates the epoll file descriptor
   87           epfd = epollCreate();
   88   
   89           // the epoll_event array passed to epoll_wait
   90           int allocationSize = NUM_EPOLLEVENTS * SIZE_EPOLLEVENT;
   91           pollArray = new AllocatedNativeObject(allocationSize, true);
   92           pollArrayAddress = pollArray.address();
   93   
   94           for (int i=0; i<NUM_EPOLLEVENTS; i++) {
   95               putEventOps(i, 0);
   96               putData(i, 0L);
   97           }
   98   
   99           // create idle set
  100           idleSet = new HashSet<SelChImpl>();
  101       }
  102   
  103       // Used to update file description registrations
  104       private static class Updator {
  105           SelChImpl channel;
  106           int opcode;
  107           int events;
  108           Updator(SelChImpl channel, int opcode, int events) {
  109               this.channel = channel;
  110               this.opcode = opcode;
  111               this.events = events;
  112           }
  113           Updator(SelChImpl channel, int opcode) {
  114               this(channel, opcode, 0);
  115           }
  116       }
  117   
  118       private LinkedList<Updator> updateList = new LinkedList<Updator>();
  119   
  120       // The epoll_event array for results from epoll_wait
  121       private AllocatedNativeObject pollArray;
  122   
  123       // The fd of the epoll driver
  124       final int epfd;
  125   
  126       // The fd of the interrupt line going out
  127       int outgoingInterruptFD;
  128   
  129       // The fd of the interrupt line coming in
  130       int incomingInterruptFD;
  131   
  132       // The index of the interrupt FD
  133       int interruptedIndex;
  134   
  135       // Number of updated pollfd entries
  136       int updated;
  137   
  138       void initInterrupt(int fd0, int fd1) {
  139           outgoingInterruptFD = fd1;
  140           incomingInterruptFD = fd0;
  141           epollCtl(epfd, EPOLL_CTL_ADD, fd0, EPOLLIN);
  142       }
  143   
  144       void putEventOps(int i, int event) {
  145           int offset = SIZE_EPOLLEVENT * i + EVENT_OFFSET;
  146           pollArray.putInt(offset, event);
  147       }
  148   
  149       void putData(int i, long value) {
  150           int offset = SIZE_EPOLLEVENT * i + DATA_OFFSET;
  151           pollArray.putLong(offset, value);
  152       }
  153   
  154       void putDescriptor(int i, int fd) {
  155           int offset = SIZE_EPOLLEVENT * i + FD_OFFSET;
  156           pollArray.putInt(offset, fd);
  157       }
  158   
  159       int getEventOps(int i) {
  160           int offset = SIZE_EPOLLEVENT * i + EVENT_OFFSET;
  161           return pollArray.getInt(offset);
  162       }
  163   
  164       int getDescriptor(int i) {
  165           int offset = SIZE_EPOLLEVENT * i + FD_OFFSET;
  166           return pollArray.getInt(offset);
  167       }
  168   
  169       /**
  170        * Update the events for a given channel.
  171        */
  172       void setInterest(SelChImpl channel, int mask) {
  173           synchronized (updateList) {
  174               // if the previous pending operation is to add this file descriptor
  175               // to epoll then update its event set
  176               if (updateList.size() > 0) {
  177                   Updator last = updateList.getLast();
  178                   if (last.channel == channel && last.opcode == EPOLL_CTL_ADD) {
  179                       last.events = mask;
  180                       return;
  181                   }
  182               }
  183   
  184               // update existing registration
  185               updateList.add(new Updator(channel, EPOLL_CTL_MOD, mask));
  186           }
  187       }
  188   
  189       /**
  190        * Add a channel's file descriptor to epoll
  191        */
  192       void add(SelChImpl channel) {
  193           synchronized (updateList) {
  194               updateList.add(new Updator(channel, EPOLL_CTL_ADD));
  195           }
  196       }
  197   
  198       /**
  199        * Remove a channel's file descriptor from epoll
  200        */
  201       void release(SelChImpl channel) {
  202           synchronized (updateList) {
  203               // flush any pending updates
  204               for (Iterator<Updator> it = updateList.iterator(); it.hasNext();) {
  205                   if (it.next().channel == channel) {
  206                       it.remove();
  207                   }
  208               }
  209   
  210               // remove from the idle set (if present)
  211               idleSet.remove(channel);
  212   
  213               // remove from epoll (if registered)
  214               epollCtl(epfd, EPOLL_CTL_DEL, channel.getFDVal(), 0);
  215           }
  216       }
  217   
  218       /**
  219        * Close epoll file descriptor and free poll array
  220        */
  221       void closeEPollFD() throws IOException {
  222           FileDispatcherImpl.closeIntFD(epfd);
  223           pollArray.free();
  224       }
  225   
  226       int poll(long timeout) throws IOException {
  227           updateRegistrations();
  228           updated = epollWait(pollArrayAddress, NUM_EPOLLEVENTS, timeout, epfd);
  229           for (int i=0; i<updated; i++) {
  230               if (getDescriptor(i) == incomingInterruptFD) {
  231                   interruptedIndex = i;
  232                   interrupted = true;
  233                   break;
  234               }
  235           }
  236           return updated;
  237       }
  238   
  239       /**
  240        * Update the pending registrations.
  241        */
  242       void updateRegistrations() {
  243           synchronized (updateList) {
  244               Updator u = null;
  245               while ((u = updateList.poll()) != null) {
  246                   SelChImpl ch = u.channel;
  247                   if (!ch.isOpen())
  248                       continue;
  249   
  250                   // if the events are 0 then file descriptor is put into "idle
  251                   // set" to prevent it being polled
  252                   if (u.events == 0) {
  253                       boolean added = idleSet.add(u.channel);
  254                       // if added to idle set then remove from epoll if registered
  255                       if (added && (u.opcode == EPOLL_CTL_MOD))
  256                           epollCtl(epfd, EPOLL_CTL_DEL, ch.getFDVal(), 0);
  257                   } else {
  258                       // events are specified. If file descriptor was in idle set
  259                       // it must be re-registered (by converting opcode to ADD)
  260                       boolean idle = false;
  261                       if (!idleSet.isEmpty())
  262                           idle = idleSet.remove(u.channel);
  263                       int opcode = (idle) ? EPOLL_CTL_ADD : u.opcode;
  264                       epollCtl(epfd, opcode, ch.getFDVal(), u.events);
  265                   }
  266               }
  267           }
  268       }
  269   
  270       // interrupt support
  271       boolean interrupted = false;
  272   
  273       public void interrupt() {
  274           interrupt(outgoingInterruptFD);
  275       }
  276   
  277       public int interruptedIndex() {
  278           return interruptedIndex;
  279       }
  280   
  281       boolean interrupted() {
  282           return interrupted;
  283       }
  284   
  285       void clearInterrupted() {
  286           interrupted = false;
  287       }
  288   
  289       static {
  290           init();
  291       }
  292   
  293       private native int epollCreate();
  294       private native void epollCtl(int epfd, int opcode, int fd, int events);
  295       private native int epollWait(long pollAddress, int numfds, long timeout,
  296                                    int epfd) throws IOException;
  297       private static native int sizeofEPollEvent();
  298       private static native int offsetofData();
  299       private static native int fdLimit();
  300       private static native void interrupt(int fd);
  301       private static native void init();
  302   }

 

posted on 2015-11-29 08:29  gyt929458988  阅读(693)  评论(0)    收藏  举报