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 185d930cadc8f62aee5f18e7921296fe66a54f18abElliott Hughesimport android.system.ErrnoException; 195d930cadc8f62aee5f18e7921296fe66a54f18abElliott Hughesimport android.system.StructPollfd; 20adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.io.FileDescriptor; 21f0d40d662d9dfdb04215c718961765837d2cf00cNeil Fullerimport java.io.InterruptedIOException; 225d930cadc8f62aee5f18e7921296fe66a54f18abElliott Hughesimport java.io.IOException; 23adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.nio.channels.ClosedSelectorException; 24adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.nio.channels.IllegalSelectorException; 25adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.nio.channels.SelectionKey; 26adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.nio.channels.Selector; 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; 31adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.util.Collection; 32adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.util.Collections; 33adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.util.HashSet; 34adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.util.Iterator; 35adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.util.Set; 3670c820401677ca251ad09ac64cc23c760764e75dElliott Hughesimport java.util.UnsafeArrayList; 370b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughesimport libcore.io.IoBridge; 3810959ae7eb41e8ceecb16378c25395eb2f29106cJesse Wilsonimport libcore.io.IoUtils; 3941f0605d2c809bd9bc1c0fb68d86b49a0f59b6c5Elliott Hughesimport libcore.io.Libcore; 40f0d40d662d9dfdb04215c718961765837d2cf00cNeil Fuller 415d930cadc8f62aee5f18e7921296fe66a54f18abElliott Hughesimport static android.system.OsConstants.EINTR; 428806710d7a5cd6a168f2463de21498c58f70948aPrzemyslaw Jakwertimport static android.system.OsConstants.POLLERR; 435d930cadc8f62aee5f18e7921296fe66a54f18abElliott Hughesimport static android.system.OsConstants.POLLHUP; 445d930cadc8f62aee5f18e7921296fe66a54f18abElliott Hughesimport static android.system.OsConstants.POLLIN; 455d930cadc8f62aee5f18e7921296fe66a54f18abElliott Hughesimport static android.system.OsConstants.POLLOUT; 46f0d40d662d9dfdb04215c718961765837d2cf00cNeil Fullerimport static java.nio.channels.SelectionKey.OP_ACCEPT; 47f0d40d662d9dfdb04215c718961765837d2cf00cNeil Fullerimport static java.nio.channels.SelectionKey.OP_CONNECT; 48f0d40d662d9dfdb04215c718961765837d2cf00cNeil Fullerimport static java.nio.channels.SelectionKey.OP_READ; 49f0d40d662d9dfdb04215c718961765837d2cf00cNeil Fullerimport static java.nio.channels.SelectionKey.OP_WRITE; 50adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 51adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/* 52adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Default implementation of java.nio.channels.Selector 53adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 54adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectfinal class SelectorImpl extends AbstractSelector { 55adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 56eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson /** 57eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson * Used to synchronize when a key's interest ops change. 58eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson */ 595e23b687ef8b3c696d54d1880b454942875665b7Elliott Hughes final Object keysLock = new Object(); 60adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 61eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson private final Set<SelectionKeyImpl> mutableKeys = new HashSet<SelectionKeyImpl>(); 62adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 63eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson /** 64eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson * The unmodifiable set of keys as exposed to the user. This object is used 65eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson * for synchronization. 66eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson */ 676b739231f8985f33f20672fe727fde0d0f023eadJesse Wilson private final Set<SelectionKey> unmodifiableKeys = Collections 68eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson .<SelectionKey>unmodifiableSet(mutableKeys); 69adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 70eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson private final Set<SelectionKey> mutableSelectedKeys = new HashSet<SelectionKey>(); 71adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 72eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson /** 73eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson * The unmodifiable set of selectable keys as seen by the user. This object 74eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson * is used for synchronization. 75eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson */ 76eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson private final Set<SelectionKey> selectedKeys 77eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson = new UnaddableSet<SelectionKey>(mutableSelectedKeys); 78eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson 79eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson /** 8010959ae7eb41e8ceecb16378c25395eb2f29106cJesse Wilson * The wakeup pipe. To trigger a wakeup, write a byte to wakeupOut. Each 8110959ae7eb41e8ceecb16378c25395eb2f29106cJesse Wilson * time select returns, wakeupIn is drained. 8260a0a96f334f159418763cab17c48a09c97cbd2fElliott Hughes */ 8310959ae7eb41e8ceecb16378c25395eb2f29106cJesse Wilson private final FileDescriptor wakeupIn; 8410959ae7eb41e8ceecb16378c25395eb2f29106cJesse Wilson private final FileDescriptor wakeupOut; 8560a0a96f334f159418763cab17c48a09c97cbd2fElliott Hughes 8670c820401677ca251ad09ac64cc23c760764e75dElliott Hughes private final UnsafeArrayList<StructPollfd> pollFds = new UnsafeArrayList<StructPollfd>(StructPollfd.class, 8); 87adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 886b739231f8985f33f20672fe727fde0d0f023eadJesse Wilson public SelectorImpl(SelectorProvider selectorProvider) throws IOException { 89adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project super(selectorProvider); 9010959ae7eb41e8ceecb16378c25395eb2f29106cJesse Wilson 9110959ae7eb41e8ceecb16378c25395eb2f29106cJesse Wilson /* 92ed3322f25d79b6607fc314d75f96d46b7c783f43Elliott Hughes * Create a pipe to trigger wakeup. We can't use a NIO pipe because it 9310959ae7eb41e8ceecb16378c25395eb2f29106cJesse Wilson * would be closed if the selecting thread is interrupted. Also 9410959ae7eb41e8ceecb16378c25395eb2f29106cJesse Wilson * configure the pipe so we can fully drain it without blocking. 9510959ae7eb41e8ceecb16378c25395eb2f29106cJesse Wilson */ 9641f0605d2c809bd9bc1c0fb68d86b49a0f59b6c5Elliott Hughes try { 9741f0605d2c809bd9bc1c0fb68d86b49a0f59b6c5Elliott Hughes FileDescriptor[] pipeFds = Libcore.os.pipe(); 9841f0605d2c809bd9bc1c0fb68d86b49a0f59b6c5Elliott Hughes wakeupIn = pipeFds[0]; 9941f0605d2c809bd9bc1c0fb68d86b49a0f59b6c5Elliott Hughes wakeupOut = pipeFds[1]; 10041f0605d2c809bd9bc1c0fb68d86b49a0f59b6c5Elliott Hughes IoUtils.setBlocking(wakeupIn, false); 10170c820401677ca251ad09ac64cc23c760764e75dElliott Hughes pollFds.add(new StructPollfd()); 10270c820401677ca251ad09ac64cc23c760764e75dElliott Hughes setPollFd(0, wakeupIn, POLLIN, null); 10341f0605d2c809bd9bc1c0fb68d86b49a0f59b6c5Elliott Hughes } catch (ErrnoException errnoException) { 10441f0605d2c809bd9bc1c0fb68d86b49a0f59b6c5Elliott Hughes throw errnoException.rethrowAsIOException(); 10541f0605d2c809bd9bc1c0fb68d86b49a0f59b6c5Elliott Hughes } 106adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 107adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1086b739231f8985f33f20672fe727fde0d0f023eadJesse Wilson @Override protected void implCloseSelector() throws IOException { 109adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project wakeup(); 110eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson synchronized (this) { 111eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson synchronized (unmodifiableKeys) { 112eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson synchronized (selectedKeys) { 11310959ae7eb41e8ceecb16378c25395eb2f29106cJesse Wilson IoUtils.close(wakeupIn); 11410959ae7eb41e8ceecb16378c25395eb2f29106cJesse Wilson IoUtils.close(wakeupOut); 115eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson doCancel(); 116eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson for (SelectionKey sk : mutableKeys) { 117eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson deregister((AbstractSelectionKey) sk); 118eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson } 119eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson } 120eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson } 121eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson } 122adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 123adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1246b739231f8985f33f20672fe727fde0d0f023eadJesse Wilson @Override protected SelectionKey register(AbstractSelectableChannel channel, 125adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int operations, Object attachment) { 126adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (!provider().equals(channel.provider())) { 127adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new IllegalSelectorException(); 128adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 129adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project synchronized (this) { 130eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson synchronized (unmodifiableKeys) { 13170c820401677ca251ad09ac64cc23c760764e75dElliott Hughes SelectionKeyImpl selectionKey = new SelectionKeyImpl(channel, operations, 13270c820401677ca251ad09ac64cc23c760764e75dElliott Hughes attachment, this); 133eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson mutableKeys.add(selectionKey); 13470c820401677ca251ad09ac64cc23c760764e75dElliott Hughes ensurePollFdsCapacity(); 135eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson return selectionKey; 136adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 137adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 138adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 139adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1406b739231f8985f33f20672fe727fde0d0f023eadJesse Wilson @Override public synchronized Set<SelectionKey> keys() { 14110959ae7eb41e8ceecb16378c25395eb2f29106cJesse Wilson checkClosed(); 142adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return unmodifiableKeys; 143adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 144adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 14510959ae7eb41e8ceecb16378c25395eb2f29106cJesse Wilson private void checkClosed() { 146adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (!isOpen()) { 147adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new ClosedSelectorException(); 148adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 149adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 150adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1516b739231f8985f33f20672fe727fde0d0f023eadJesse Wilson @Override public int select() throws IOException { 15270c820401677ca251ad09ac64cc23c760764e75dElliott Hughes // Blocks until some fd is ready. 15370c820401677ca251ad09ac64cc23c760764e75dElliott Hughes return selectInternal(-1); 154adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 155adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1566b739231f8985f33f20672fe727fde0d0f023eadJesse Wilson @Override public int select(long timeout) throws IOException { 157adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (timeout < 0) { 158126ab1b546c71137a97cef68cc89267e7f7be634Elliott Hughes throw new IllegalArgumentException("timeout < 0: " + timeout); 159adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 16070c820401677ca251ad09ac64cc23c760764e75dElliott Hughes // Our timeout is interpreted differently to Unix's --- 0 means block. See selectNow. 16170c820401677ca251ad09ac64cc23c760764e75dElliott Hughes return selectInternal((timeout == 0) ? -1 : timeout); 162adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 163adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1646b739231f8985f33f20672fe727fde0d0f023eadJesse Wilson @Override public int selectNow() throws IOException { 16570c820401677ca251ad09ac64cc23c760764e75dElliott Hughes return selectInternal(0); 166adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 167adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 168adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private int selectInternal(long timeout) throws IOException { 16910959ae7eb41e8ceecb16378c25395eb2f29106cJesse Wilson checkClosed(); 170adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project synchronized (this) { 171eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson synchronized (unmodifiableKeys) { 172adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project synchronized (selectedKeys) { 173adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project doCancel(); 174318d6de23bec3024a85eb211f5843d925774622aElliott Hughes boolean isBlocking = (timeout != 0); 175eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson synchronized (keysLock) { 17670c820401677ca251ad09ac64cc23c760764e75dElliott Hughes preparePollFds(); 177eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson } 178f7bd2a99f6f4024e9034300b30a13a2ea871aa97Elliott Hughes int rc = -1; 179adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project try { 180318d6de23bec3024a85eb211f5843d925774622aElliott Hughes if (isBlocking) { 181adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project begin(); 182adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1839b510df35b57946d843ffc34cf23fdcfc84c5220Elliott Hughes try { 1849b510df35b57946d843ffc34cf23fdcfc84c5220Elliott Hughes rc = Libcore.os.poll(pollFds.array(), (int) timeout); 1859b510df35b57946d843ffc34cf23fdcfc84c5220Elliott Hughes } catch (ErrnoException errnoException) { 186f7bd2a99f6f4024e9034300b30a13a2ea871aa97Elliott Hughes if (errnoException.errno != EINTR) { 187f7bd2a99f6f4024e9034300b30a13a2ea871aa97Elliott Hughes throw errnoException.rethrowAsIOException(); 188f7bd2a99f6f4024e9034300b30a13a2ea871aa97Elliott Hughes } 1899b510df35b57946d843ffc34cf23fdcfc84c5220Elliott Hughes } 190adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } finally { 191318d6de23bec3024a85eb211f5843d925774622aElliott Hughes if (isBlocking) { 192adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project end(); 193adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 194adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 195eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson 19670c820401677ca251ad09ac64cc23c760764e75dElliott Hughes int readyCount = (rc > 0) ? processPollFds() : 0; 19770c820401677ca251ad09ac64cc23c760764e75dElliott Hughes readyCount -= doCancel(); 19870c820401677ca251ad09ac64cc23c760764e75dElliott Hughes return readyCount; 199adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 200adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 201adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 202adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 203adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 20470c820401677ca251ad09ac64cc23c760764e75dElliott Hughes private void setPollFd(int i, FileDescriptor fd, int events, Object object) { 20570c820401677ca251ad09ac64cc23c760764e75dElliott Hughes StructPollfd pollFd = pollFds.get(i); 20670c820401677ca251ad09ac64cc23c760764e75dElliott Hughes pollFd.fd = fd; 20770c820401677ca251ad09ac64cc23c760764e75dElliott Hughes pollFd.events = (short) events; 20870c820401677ca251ad09ac64cc23c760764e75dElliott Hughes pollFd.userData = object; 20970c820401677ca251ad09ac64cc23c760764e75dElliott Hughes } 210adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 21170c820401677ca251ad09ac64cc23c760764e75dElliott Hughes private void preparePollFds() { 21270c820401677ca251ad09ac64cc23c760764e75dElliott Hughes int i = 1; // Our wakeup pipe comes before all the user's fds. 213eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson for (SelectionKeyImpl key : mutableKeys) { 214eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson int interestOps = key.interestOpsNoCheck(); 21570c820401677ca251ad09ac64cc23c760764e75dElliott Hughes short eventMask = 0; 216a7bb29434692e01aed843b88cd042628bab74a23Elliott Hughes if (((OP_ACCEPT | OP_READ) & interestOps) != 0) { 21770c820401677ca251ad09ac64cc23c760764e75dElliott Hughes eventMask |= POLLIN; 218eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson } 219a7bb29434692e01aed843b88cd042628bab74a23Elliott Hughes if (((OP_CONNECT | OP_WRITE) & interestOps) != 0) { 22070c820401677ca251ad09ac64cc23c760764e75dElliott Hughes eventMask |= POLLOUT; 22170c820401677ca251ad09ac64cc23c760764e75dElliott Hughes } 22270c820401677ca251ad09ac64cc23c760764e75dElliott Hughes if (eventMask != 0) { 22370c820401677ca251ad09ac64cc23c760764e75dElliott Hughes setPollFd(i++, ((FileDescriptorChannel) key.channel()).getFD(), eventMask, key); 224adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 225adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 226adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 227adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 22870c820401677ca251ad09ac64cc23c760764e75dElliott Hughes private void ensurePollFdsCapacity() { 22970c820401677ca251ad09ac64cc23c760764e75dElliott Hughes // We need one slot for each element of mutableKeys, plus one for the wakeup pipe. 23070c820401677ca251ad09ac64cc23c760764e75dElliott Hughes while (pollFds.size() < mutableKeys.size() + 1) { 23170c820401677ca251ad09ac64cc23c760764e75dElliott Hughes pollFds.add(new StructPollfd()); 23270c820401677ca251ad09ac64cc23c760764e75dElliott Hughes } 23370c820401677ca251ad09ac64cc23c760764e75dElliott Hughes } 23470c820401677ca251ad09ac64cc23c760764e75dElliott Hughes 235eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson /** 23670c820401677ca251ad09ac64cc23c760764e75dElliott Hughes * Updates the key ready ops and selected key set. 237eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson */ 23870c820401677ca251ad09ac64cc23c760764e75dElliott Hughes private int processPollFds() throws IOException { 23970c820401677ca251ad09ac64cc23c760764e75dElliott Hughes if (pollFds.get(0).revents == POLLIN) { 24026c7025a7a919044771fb89031161bd26fe03032Elliott Hughes // Read bytes from the wakeup pipe until the pipe is empty. 24110959ae7eb41e8ceecb16378c25395eb2f29106cJesse Wilson byte[] buffer = new byte[8]; 2420b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes while (IoBridge.read(wakeupIn, buffer, 0, 1) > 0) { 243adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 244adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 245eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson 24670c820401677ca251ad09ac64cc23c760764e75dElliott Hughes int readyKeyCount = 0; 24770c820401677ca251ad09ac64cc23c760764e75dElliott Hughes for (int i = 1; i < pollFds.size(); ++i) { 24870c820401677ca251ad09ac64cc23c760764e75dElliott Hughes StructPollfd pollFd = pollFds.get(i); 24970c820401677ca251ad09ac64cc23c760764e75dElliott Hughes if (pollFd.revents == 0) { 250adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project continue; 251adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 25270c820401677ca251ad09ac64cc23c760764e75dElliott Hughes if (pollFd.fd == null) { 25370c820401677ca251ad09ac64cc23c760764e75dElliott Hughes break; 25470c820401677ca251ad09ac64cc23c760764e75dElliott Hughes } 25570c820401677ca251ad09ac64cc23c760764e75dElliott Hughes 25670c820401677ca251ad09ac64cc23c760764e75dElliott Hughes SelectionKeyImpl key = (SelectionKeyImpl) pollFd.userData; 25770c820401677ca251ad09ac64cc23c760764e75dElliott Hughes 25870c820401677ca251ad09ac64cc23c760764e75dElliott Hughes pollFd.fd = null; 25970c820401677ca251ad09ac64cc23c760764e75dElliott Hughes pollFd.userData = null; 260eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson 261eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson int ops = key.interestOpsNoCheck(); 26257656d21f772aacbe0d05e54b1274f4c58993a52Elliott Hughes int selectedOps = 0; 2638806710d7a5cd6a168f2463de21498c58f70948aPrzemyslaw Jakwert if ((pollFd.revents & POLLHUP) != 0 || (pollFd.revents & POLLERR) != 0) { 264ed3322f25d79b6607fc314d75f96d46b7c783f43Elliott Hughes // If there was an error condition, we definitely want to wake listeners, 265ed3322f25d79b6607fc314d75f96d46b7c783f43Elliott Hughes // regardless of what they're waiting for. Failure is always interesting. 266ed3322f25d79b6607fc314d75f96d46b7c783f43Elliott Hughes selectedOps |= ops; 267ed3322f25d79b6607fc314d75f96d46b7c783f43Elliott Hughes } 26870c820401677ca251ad09ac64cc23c760764e75dElliott Hughes if ((pollFd.revents & POLLIN) != 0) { 26957656d21f772aacbe0d05e54b1274f4c58993a52Elliott Hughes selectedOps |= ops & (OP_ACCEPT | OP_READ); 27057656d21f772aacbe0d05e54b1274f4c58993a52Elliott Hughes } 27157656d21f772aacbe0d05e54b1274f4c58993a52Elliott Hughes if ((pollFd.revents & POLLOUT) != 0) { 27270c820401677ca251ad09ac64cc23c760764e75dElliott Hughes if (key.isConnected()) { 27357656d21f772aacbe0d05e54b1274f4c58993a52Elliott Hughes selectedOps |= ops & OP_WRITE; 27470c820401677ca251ad09ac64cc23c760764e75dElliott Hughes } else { 27557656d21f772aacbe0d05e54b1274f4c58993a52Elliott Hughes selectedOps |= ops & OP_CONNECT; 27670c820401677ca251ad09ac64cc23c760764e75dElliott Hughes } 277adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 278adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 27957656d21f772aacbe0d05e54b1274f4c58993a52Elliott Hughes if (selectedOps != 0) { 280eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson boolean wasSelected = mutableSelectedKeys.contains(key); 28157656d21f772aacbe0d05e54b1274f4c58993a52Elliott Hughes if (wasSelected && key.readyOps() != selectedOps) { 28257656d21f772aacbe0d05e54b1274f4c58993a52Elliott Hughes key.setReadyOps(key.readyOps() | selectedOps); 28370c820401677ca251ad09ac64cc23c760764e75dElliott Hughes ++readyKeyCount; 284eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson } else if (!wasSelected) { 28557656d21f772aacbe0d05e54b1274f4c58993a52Elliott Hughes key.setReadyOps(selectedOps); 286eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson mutableSelectedKeys.add(key); 28770c820401677ca251ad09ac64cc23c760764e75dElliott Hughes ++readyKeyCount; 288adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 289adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 290adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 291eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson 29270c820401677ca251ad09ac64cc23c760764e75dElliott Hughes return readyKeyCount; 293adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 294adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 2956b739231f8985f33f20672fe727fde0d0f023eadJesse Wilson @Override public synchronized Set<SelectionKey> selectedKeys() { 29610959ae7eb41e8ceecb16378c25395eb2f29106cJesse Wilson checkClosed(); 297eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson return selectedKeys; 298adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 299adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 300eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson /** 301eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson * Removes cancelled keys from the key set and selected key set, and 302ed3322f25d79b6607fc314d75f96d46b7c783f43Elliott Hughes * unregisters the corresponding channels. Returns the number of keys 303eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson * removed from the selected key set. 304eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson */ 305eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson private int doCancel() { 306eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson int deselected = 0; 307eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson 308adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project Set<SelectionKey> cancelledKeys = cancelledKeys(); 309adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project synchronized (cancelledKeys) { 310adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (cancelledKeys.size() > 0) { 31160a0a96f334f159418763cab17c48a09c97cbd2fElliott Hughes for (SelectionKey currentKey : cancelledKeys) { 31260a0a96f334f159418763cab17c48a09c97cbd2fElliott Hughes mutableKeys.remove(currentKey); 31360a0a96f334f159418763cab17c48a09c97cbd2fElliott Hughes deregister((AbstractSelectionKey) currentKey); 31460a0a96f334f159418763cab17c48a09c97cbd2fElliott Hughes if (mutableSelectedKeys.remove(currentKey)) { 315eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson deselected++; 316eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson } 317adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 318eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson cancelledKeys.clear(); 319adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 320adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 321eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson 322eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson return deselected; 323adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 324adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 3256b739231f8985f33f20672fe727fde0d0f023eadJesse Wilson @Override public Selector wakeup() { 326adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project try { 32778c7cc547101002b9f9043cf3845970719d1bda8Elliott Hughes Libcore.os.write(wakeupOut, new byte[] { 1 }, 0, 1); 32878c7cc547101002b9f9043cf3845970719d1bda8Elliott Hughes } catch (ErrnoException ignored) { 329f0d40d662d9dfdb04215c718961765837d2cf00cNeil Fuller } catch (InterruptedIOException ignored) { 330adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 331adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return this; 332adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 333adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 334adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private static class UnaddableSet<E> implements Set<E> { 335adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 336eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson private final Set<E> set; 337adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 338adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project UnaddableSet(Set<E> set) { 339adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project this.set = set; 340adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 341adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 342eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson @Override 343adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public boolean equals(Object object) { 344adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return set.equals(object); 345adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 346adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 347eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson @Override 348adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public int hashCode() { 349adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return set.hashCode(); 350adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 351adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 352adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public boolean add(E object) { 353adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new UnsupportedOperationException(); 354adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 355adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 356adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public boolean addAll(Collection<? extends E> c) { 357adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new UnsupportedOperationException(); 358adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 359adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 360adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public void clear() { 361adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project set.clear(); 362adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 363adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 364adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public boolean contains(Object object) { 365adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return set.contains(object); 366adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 367adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 368adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public boolean containsAll(Collection<?> c) { 369adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return set.containsAll(c); 370adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 371adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 372adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public boolean isEmpty() { 373adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return set.isEmpty(); 374adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 375adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 376adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public Iterator<E> iterator() { 377adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return set.iterator(); 378adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 379adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 380adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public boolean remove(Object object) { 381adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return set.remove(object); 382adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 383adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 384adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public boolean removeAll(Collection<?> c) { 385adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return set.removeAll(c); 386adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 387adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 388adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public boolean retainAll(Collection<?> c) { 389adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return set.retainAll(c); 390adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 391adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 392adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public int size() { 393adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return set.size(); 394adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 395adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 396adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public Object[] toArray() { 397adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return set.toArray(); 398adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 399adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 400adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public <T> T[] toArray(T[] a) { 401adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return set.toArray(a); 402adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 403adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 404adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 405