1adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/* Licensed to the Apache Software Foundation (ASF) under one or more 2adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * contributor license agreements. See the NOTICE file distributed with 3adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * this work for additional information regarding copyright ownership. 4adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * The ASF licenses this file to You under the Apache License, Version 2.0 5adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * (the "License"); you may not use this file except in compliance with 6adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the License. You may obtain a copy of the License at 7eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson * 8adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 9eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson * 10adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Unless required by applicable law or agreed to in writing, software 11adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 12adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * See the License for the specific language governing permissions and 14adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * limitations under the License. 15adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 16ae704b984c10a63883cc366e823d53902d6ac7a9Elliott Hughespackage java.nio; 17adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 18adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.io.FileDescriptor; 19adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.io.IOException; 20adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.nio.channels.ClosedSelectorException; 21adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.nio.channels.IllegalSelectorException; 227365de1056414750d0a7d1fdd26025fd247f0d04Jesse Wilsonimport java.nio.channels.SelectableChannel; 23adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.nio.channels.SelectionKey; 24eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilsonimport static java.nio.channels.SelectionKey.*; 25adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.nio.channels.Selector; 26b960e1a9d80af9536f77172cbe3932c3afc7e7e4Marc Petit-Hugueninimport java.nio.channels.SocketChannel; 27adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.nio.channels.spi.AbstractSelectableChannel; 28adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.nio.channels.spi.AbstractSelectionKey; 29adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.nio.channels.spi.AbstractSelector; 30adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.nio.channels.spi.SelectorProvider; 31eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilsonimport java.util.Arrays; 32adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.util.Collection; 33adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.util.Collections; 34adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.util.HashSet; 35adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.util.Iterator; 36adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.util.Set; 3770c820401677ca251ad09ac64cc23c760764e75dElliott Hughesimport java.util.UnsafeArrayList; 3841f0605d2c809bd9bc1c0fb68d86b49a0f59b6c5Elliott Hughesimport libcore.io.ErrnoException; 390b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughesimport libcore.io.IoBridge; 4010959ae7eb41e8ceecb16378c25395eb2f29106cJesse Wilsonimport libcore.io.IoUtils; 4141f0605d2c809bd9bc1c0fb68d86b49a0f59b6c5Elliott Hughesimport libcore.io.Libcore; 4270c820401677ca251ad09ac64cc23c760764e75dElliott Hughesimport libcore.io.StructPollfd; 436186821cb13f4ac7ff50950c813394367e021eaeJesse Wilsonimport libcore.util.EmptyArray; 4470c820401677ca251ad09ac64cc23c760764e75dElliott Hughesimport static libcore.io.OsConstants.*; 45adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 46adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/* 47adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Default implementation of java.nio.channels.Selector 48adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 49adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectfinal class SelectorImpl extends AbstractSelector { 50adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 51eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson /** 52eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson * Used to synchronize when a key's interest ops change. 53eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson */ 545e23b687ef8b3c696d54d1880b454942875665b7Elliott Hughes final Object keysLock = new Object(); 55adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 56eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson private final Set<SelectionKeyImpl> mutableKeys = new HashSet<SelectionKeyImpl>(); 57adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 58eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson /** 59eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson * The unmodifiable set of keys as exposed to the user. This object is used 60eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson * for synchronization. 61eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson */ 626b739231f8985f33f20672fe727fde0d0f023eadJesse Wilson private final Set<SelectionKey> unmodifiableKeys = Collections 63eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson .<SelectionKey>unmodifiableSet(mutableKeys); 64adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 65eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson private final Set<SelectionKey> mutableSelectedKeys = new HashSet<SelectionKey>(); 66adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 67eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson /** 68eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson * The unmodifiable set of selectable keys as seen by the user. This object 69eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson * is used for synchronization. 70eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson */ 71eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson private final Set<SelectionKey> selectedKeys 72eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson = new UnaddableSet<SelectionKey>(mutableSelectedKeys); 73eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson 74eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson /** 7510959ae7eb41e8ceecb16378c25395eb2f29106cJesse Wilson * The wakeup pipe. To trigger a wakeup, write a byte to wakeupOut. Each 7610959ae7eb41e8ceecb16378c25395eb2f29106cJesse Wilson * time select returns, wakeupIn is drained. 7760a0a96f334f159418763cab17c48a09c97cbd2fElliott Hughes */ 7810959ae7eb41e8ceecb16378c25395eb2f29106cJesse Wilson private final FileDescriptor wakeupIn; 7910959ae7eb41e8ceecb16378c25395eb2f29106cJesse Wilson private final FileDescriptor wakeupOut; 8060a0a96f334f159418763cab17c48a09c97cbd2fElliott Hughes 8170c820401677ca251ad09ac64cc23c760764e75dElliott Hughes private final UnsafeArrayList<StructPollfd> pollFds = new UnsafeArrayList<StructPollfd>(StructPollfd.class, 8); 82adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 836b739231f8985f33f20672fe727fde0d0f023eadJesse Wilson public SelectorImpl(SelectorProvider selectorProvider) throws IOException { 84adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project super(selectorProvider); 8510959ae7eb41e8ceecb16378c25395eb2f29106cJesse Wilson 8610959ae7eb41e8ceecb16378c25395eb2f29106cJesse Wilson /* 8710959ae7eb41e8ceecb16378c25395eb2f29106cJesse Wilson * Create a pipes to trigger wakeup. We can't use a NIO pipe because it 8810959ae7eb41e8ceecb16378c25395eb2f29106cJesse Wilson * would be closed if the selecting thread is interrupted. Also 8910959ae7eb41e8ceecb16378c25395eb2f29106cJesse Wilson * configure the pipe so we can fully drain it without blocking. 9010959ae7eb41e8ceecb16378c25395eb2f29106cJesse Wilson */ 9141f0605d2c809bd9bc1c0fb68d86b49a0f59b6c5Elliott Hughes try { 9241f0605d2c809bd9bc1c0fb68d86b49a0f59b6c5Elliott Hughes FileDescriptor[] pipeFds = Libcore.os.pipe(); 9341f0605d2c809bd9bc1c0fb68d86b49a0f59b6c5Elliott Hughes wakeupIn = pipeFds[0]; 9441f0605d2c809bd9bc1c0fb68d86b49a0f59b6c5Elliott Hughes wakeupOut = pipeFds[1]; 9541f0605d2c809bd9bc1c0fb68d86b49a0f59b6c5Elliott Hughes IoUtils.setBlocking(wakeupIn, false); 9670c820401677ca251ad09ac64cc23c760764e75dElliott Hughes pollFds.add(new StructPollfd()); 9770c820401677ca251ad09ac64cc23c760764e75dElliott Hughes setPollFd(0, wakeupIn, POLLIN, null); 9841f0605d2c809bd9bc1c0fb68d86b49a0f59b6c5Elliott Hughes } catch (ErrnoException errnoException) { 9941f0605d2c809bd9bc1c0fb68d86b49a0f59b6c5Elliott Hughes throw errnoException.rethrowAsIOException(); 10041f0605d2c809bd9bc1c0fb68d86b49a0f59b6c5Elliott Hughes } 101adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 102adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1036b739231f8985f33f20672fe727fde0d0f023eadJesse Wilson @Override protected void implCloseSelector() throws IOException { 104adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project wakeup(); 105eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson synchronized (this) { 106eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson synchronized (unmodifiableKeys) { 107eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson synchronized (selectedKeys) { 10810959ae7eb41e8ceecb16378c25395eb2f29106cJesse Wilson IoUtils.close(wakeupIn); 10910959ae7eb41e8ceecb16378c25395eb2f29106cJesse Wilson IoUtils.close(wakeupOut); 110eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson doCancel(); 111eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson for (SelectionKey sk : mutableKeys) { 112eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson deregister((AbstractSelectionKey) sk); 113eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson } 114eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson } 115eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson } 116eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson } 117adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 118adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1196b739231f8985f33f20672fe727fde0d0f023eadJesse Wilson @Override protected SelectionKey register(AbstractSelectableChannel channel, 120adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int operations, Object attachment) { 121adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (!provider().equals(channel.provider())) { 122adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new IllegalSelectorException(); 123adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 124adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project synchronized (this) { 125eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson synchronized (unmodifiableKeys) { 12670c820401677ca251ad09ac64cc23c760764e75dElliott Hughes SelectionKeyImpl selectionKey = new SelectionKeyImpl(channel, operations, 12770c820401677ca251ad09ac64cc23c760764e75dElliott Hughes attachment, this); 128eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson mutableKeys.add(selectionKey); 12970c820401677ca251ad09ac64cc23c760764e75dElliott Hughes ensurePollFdsCapacity(); 130eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson return selectionKey; 131adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 132adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 133adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 134adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1356b739231f8985f33f20672fe727fde0d0f023eadJesse Wilson @Override public synchronized Set<SelectionKey> keys() { 13610959ae7eb41e8ceecb16378c25395eb2f29106cJesse Wilson checkClosed(); 137adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return unmodifiableKeys; 138adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 139adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 14010959ae7eb41e8ceecb16378c25395eb2f29106cJesse Wilson private void checkClosed() { 141adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (!isOpen()) { 142adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new ClosedSelectorException(); 143adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 144adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 145adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1466b739231f8985f33f20672fe727fde0d0f023eadJesse Wilson @Override public int select() throws IOException { 14770c820401677ca251ad09ac64cc23c760764e75dElliott Hughes // Blocks until some fd is ready. 14870c820401677ca251ad09ac64cc23c760764e75dElliott Hughes return selectInternal(-1); 149adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 150adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1516b739231f8985f33f20672fe727fde0d0f023eadJesse Wilson @Override public int select(long timeout) throws IOException { 152adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (timeout < 0) { 153126ab1b546c71137a97cef68cc89267e7f7be634Elliott Hughes throw new IllegalArgumentException("timeout < 0: " + timeout); 154adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 15570c820401677ca251ad09ac64cc23c760764e75dElliott Hughes // Our timeout is interpreted differently to Unix's --- 0 means block. See selectNow. 15670c820401677ca251ad09ac64cc23c760764e75dElliott Hughes return selectInternal((timeout == 0) ? -1 : timeout); 157adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 158adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1596b739231f8985f33f20672fe727fde0d0f023eadJesse Wilson @Override public int selectNow() throws IOException { 16070c820401677ca251ad09ac64cc23c760764e75dElliott Hughes return selectInternal(0); 161adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 162adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 163adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private int selectInternal(long timeout) throws IOException { 16410959ae7eb41e8ceecb16378c25395eb2f29106cJesse Wilson checkClosed(); 165adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project synchronized (this) { 166eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson synchronized (unmodifiableKeys) { 167adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project synchronized (selectedKeys) { 168adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project doCancel(); 16970c820401677ca251ad09ac64cc23c760764e75dElliott Hughes boolean isBlock = (timeout != 0); 170eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson synchronized (keysLock) { 17170c820401677ca251ad09ac64cc23c760764e75dElliott Hughes preparePollFds(); 172eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson } 173f7bd2a99f6f4024e9034300b30a13a2ea871aa97Elliott Hughes int rc = -1; 174adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project try { 175adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (isBlock) { 176adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project begin(); 177adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1789b510df35b57946d843ffc34cf23fdcfc84c5220Elliott Hughes try { 1799b510df35b57946d843ffc34cf23fdcfc84c5220Elliott Hughes rc = Libcore.os.poll(pollFds.array(), (int) timeout); 1809b510df35b57946d843ffc34cf23fdcfc84c5220Elliott Hughes } catch (ErrnoException errnoException) { 181f7bd2a99f6f4024e9034300b30a13a2ea871aa97Elliott Hughes if (errnoException.errno != EINTR) { 182f7bd2a99f6f4024e9034300b30a13a2ea871aa97Elliott Hughes throw errnoException.rethrowAsIOException(); 183f7bd2a99f6f4024e9034300b30a13a2ea871aa97Elliott Hughes } 1849b510df35b57946d843ffc34cf23fdcfc84c5220Elliott Hughes } 185adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } finally { 186adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (isBlock) { 187adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project end(); 188adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 189adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 190eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson 19170c820401677ca251ad09ac64cc23c760764e75dElliott Hughes int readyCount = (rc > 0) ? processPollFds() : 0; 19270c820401677ca251ad09ac64cc23c760764e75dElliott Hughes readyCount -= doCancel(); 19370c820401677ca251ad09ac64cc23c760764e75dElliott Hughes return readyCount; 194adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 195adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 196adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 197adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 198adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 19970c820401677ca251ad09ac64cc23c760764e75dElliott Hughes private void setPollFd(int i, FileDescriptor fd, int events, Object object) { 20070c820401677ca251ad09ac64cc23c760764e75dElliott Hughes StructPollfd pollFd = pollFds.get(i); 20170c820401677ca251ad09ac64cc23c760764e75dElliott Hughes pollFd.fd = fd; 20270c820401677ca251ad09ac64cc23c760764e75dElliott Hughes pollFd.events = (short) events; 20370c820401677ca251ad09ac64cc23c760764e75dElliott Hughes pollFd.userData = object; 20470c820401677ca251ad09ac64cc23c760764e75dElliott Hughes } 205adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 20670c820401677ca251ad09ac64cc23c760764e75dElliott Hughes private void preparePollFds() { 20770c820401677ca251ad09ac64cc23c760764e75dElliott Hughes int i = 1; // Our wakeup pipe comes before all the user's fds. 208eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson for (SelectionKeyImpl key : mutableKeys) { 209eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson int interestOps = key.interestOpsNoCheck(); 21070c820401677ca251ad09ac64cc23c760764e75dElliott Hughes short eventMask = 0; 211a7bb29434692e01aed843b88cd042628bab74a23Elliott Hughes if (((OP_ACCEPT | OP_READ) & interestOps) != 0) { 21270c820401677ca251ad09ac64cc23c760764e75dElliott Hughes eventMask |= POLLIN; 213eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson } 214a7bb29434692e01aed843b88cd042628bab74a23Elliott Hughes if (((OP_CONNECT | OP_WRITE) & interestOps) != 0) { 21570c820401677ca251ad09ac64cc23c760764e75dElliott Hughes eventMask |= POLLOUT; 21670c820401677ca251ad09ac64cc23c760764e75dElliott Hughes } 21770c820401677ca251ad09ac64cc23c760764e75dElliott Hughes if (eventMask != 0) { 21870c820401677ca251ad09ac64cc23c760764e75dElliott Hughes setPollFd(i++, ((FileDescriptorChannel) key.channel()).getFD(), eventMask, key); 219adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 220adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 221adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 222adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 22370c820401677ca251ad09ac64cc23c760764e75dElliott Hughes private void ensurePollFdsCapacity() { 22470c820401677ca251ad09ac64cc23c760764e75dElliott Hughes // We need one slot for each element of mutableKeys, plus one for the wakeup pipe. 22570c820401677ca251ad09ac64cc23c760764e75dElliott Hughes while (pollFds.size() < mutableKeys.size() + 1) { 22670c820401677ca251ad09ac64cc23c760764e75dElliott Hughes pollFds.add(new StructPollfd()); 22770c820401677ca251ad09ac64cc23c760764e75dElliott Hughes } 22870c820401677ca251ad09ac64cc23c760764e75dElliott Hughes } 22970c820401677ca251ad09ac64cc23c760764e75dElliott Hughes 230eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson /** 23170c820401677ca251ad09ac64cc23c760764e75dElliott Hughes * Updates the key ready ops and selected key set. 232eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson */ 23370c820401677ca251ad09ac64cc23c760764e75dElliott Hughes private int processPollFds() throws IOException { 23470c820401677ca251ad09ac64cc23c760764e75dElliott Hughes if (pollFds.get(0).revents == POLLIN) { 23526c7025a7a919044771fb89031161bd26fe03032Elliott Hughes // Read bytes from the wakeup pipe until the pipe is empty. 23610959ae7eb41e8ceecb16378c25395eb2f29106cJesse Wilson byte[] buffer = new byte[8]; 2370b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes while (IoBridge.read(wakeupIn, buffer, 0, 1) > 0) { 238adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 239adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 240eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson 24170c820401677ca251ad09ac64cc23c760764e75dElliott Hughes int readyKeyCount = 0; 24270c820401677ca251ad09ac64cc23c760764e75dElliott Hughes for (int i = 1; i < pollFds.size(); ++i) { 24370c820401677ca251ad09ac64cc23c760764e75dElliott Hughes StructPollfd pollFd = pollFds.get(i); 24470c820401677ca251ad09ac64cc23c760764e75dElliott Hughes if (pollFd.revents == 0) { 245adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project continue; 246adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 24770c820401677ca251ad09ac64cc23c760764e75dElliott Hughes if (pollFd.fd == null) { 24870c820401677ca251ad09ac64cc23c760764e75dElliott Hughes break; 24970c820401677ca251ad09ac64cc23c760764e75dElliott Hughes } 25070c820401677ca251ad09ac64cc23c760764e75dElliott Hughes 25170c820401677ca251ad09ac64cc23c760764e75dElliott Hughes SelectionKeyImpl key = (SelectionKeyImpl) pollFd.userData; 25270c820401677ca251ad09ac64cc23c760764e75dElliott Hughes 25370c820401677ca251ad09ac64cc23c760764e75dElliott Hughes pollFd.fd = null; 25470c820401677ca251ad09ac64cc23c760764e75dElliott Hughes pollFd.userData = null; 255eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson 256eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson int ops = key.interestOpsNoCheck(); 257adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int selectedOp = 0; 25870c820401677ca251ad09ac64cc23c760764e75dElliott Hughes if ((pollFd.revents & POLLIN) != 0) { 25970c820401677ca251ad09ac64cc23c760764e75dElliott Hughes selectedOp = ops & (OP_ACCEPT | OP_READ); 26070c820401677ca251ad09ac64cc23c760764e75dElliott Hughes } else if ((pollFd.revents & POLLOUT) != 0) { 26170c820401677ca251ad09ac64cc23c760764e75dElliott Hughes if (key.isConnected()) { 26270c820401677ca251ad09ac64cc23c760764e75dElliott Hughes selectedOp = ops & OP_WRITE; 26370c820401677ca251ad09ac64cc23c760764e75dElliott Hughes } else { 26470c820401677ca251ad09ac64cc23c760764e75dElliott Hughes selectedOp = ops & OP_CONNECT; 26570c820401677ca251ad09ac64cc23c760764e75dElliott Hughes } 266adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 267adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 26860a0a96f334f159418763cab17c48a09c97cbd2fElliott Hughes if (selectedOp != 0) { 269eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson boolean wasSelected = mutableSelectedKeys.contains(key); 270eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson if (wasSelected && key.readyOps() != selectedOp) { 271adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project key.setReadyOps(key.readyOps() | selectedOp); 27270c820401677ca251ad09ac64cc23c760764e75dElliott Hughes ++readyKeyCount; 273eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson } else if (!wasSelected) { 274adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project key.setReadyOps(selectedOp); 275eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson mutableSelectedKeys.add(key); 27670c820401677ca251ad09ac64cc23c760764e75dElliott Hughes ++readyKeyCount; 277adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 278adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 279adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 280eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson 28170c820401677ca251ad09ac64cc23c760764e75dElliott Hughes return readyKeyCount; 282adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 283adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 2846b739231f8985f33f20672fe727fde0d0f023eadJesse Wilson @Override public synchronized Set<SelectionKey> selectedKeys() { 28510959ae7eb41e8ceecb16378c25395eb2f29106cJesse Wilson checkClosed(); 286eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson return selectedKeys; 287adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 288adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 289eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson /** 290eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson * Removes cancelled keys from the key set and selected key set, and 291eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson * deregisters the corresponding channels. Returns the number of keys 292eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson * removed from the selected key set. 293eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson */ 294eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson private int doCancel() { 295eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson int deselected = 0; 296eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson 297adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project Set<SelectionKey> cancelledKeys = cancelledKeys(); 298adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project synchronized (cancelledKeys) { 299adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (cancelledKeys.size() > 0) { 30060a0a96f334f159418763cab17c48a09c97cbd2fElliott Hughes for (SelectionKey currentKey : cancelledKeys) { 30160a0a96f334f159418763cab17c48a09c97cbd2fElliott Hughes mutableKeys.remove(currentKey); 30260a0a96f334f159418763cab17c48a09c97cbd2fElliott Hughes deregister((AbstractSelectionKey) currentKey); 30360a0a96f334f159418763cab17c48a09c97cbd2fElliott Hughes if (mutableSelectedKeys.remove(currentKey)) { 304eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson deselected++; 305eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson } 306adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 307eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson cancelledKeys.clear(); 308adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 309adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 310eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson 311eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson return deselected; 312adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 313adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 3146b739231f8985f33f20672fe727fde0d0f023eadJesse Wilson @Override public Selector wakeup() { 315adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project try { 31678c7cc547101002b9f9043cf3845970719d1bda8Elliott Hughes Libcore.os.write(wakeupOut, new byte[] { 1 }, 0, 1); 31778c7cc547101002b9f9043cf3845970719d1bda8Elliott Hughes } catch (ErrnoException ignored) { 318adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 319adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return this; 320adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 321adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 322adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private static class UnaddableSet<E> implements Set<E> { 323adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 324eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson private final Set<E> set; 325adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 326adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project UnaddableSet(Set<E> set) { 327adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project this.set = set; 328adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 329adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 330eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson @Override 331adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public boolean equals(Object object) { 332adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return set.equals(object); 333adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 334adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 335eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson @Override 336adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public int hashCode() { 337adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return set.hashCode(); 338adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 339adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 340adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public boolean add(E object) { 341adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new UnsupportedOperationException(); 342adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 343adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 344adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public boolean addAll(Collection<? extends E> c) { 345adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new UnsupportedOperationException(); 346adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 347adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 348adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public void clear() { 349adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project set.clear(); 350adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 351adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 352adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public boolean contains(Object object) { 353adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return set.contains(object); 354adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 355adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 356adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public boolean containsAll(Collection<?> c) { 357adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return set.containsAll(c); 358adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 359adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 360adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public boolean isEmpty() { 361adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return set.isEmpty(); 362adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 363adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 364adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public Iterator<E> iterator() { 365adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return set.iterator(); 366adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 367adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 368adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public boolean remove(Object object) { 369adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return set.remove(object); 370adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 371adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 372adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public boolean removeAll(Collection<?> c) { 373adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return set.removeAll(c); 374adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 375adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 376adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public boolean retainAll(Collection<?> c) { 377adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return set.retainAll(c); 378adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 379adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 380adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public int size() { 381adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return set.size(); 382adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 383adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 384adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public Object[] toArray() { 385adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return set.toArray(); 386adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 387adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 388adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public <T> T[] toArray(T[] a) { 389adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return set.toArray(a); 390adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 391adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 392adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 393