src/java.base/share/classes/sun/nio/ch/SelectorImpl.java
changeset 58439 b25362cec8ce
parent 50602 ed8de3d0cd28
child 58496 7f34de3cdfe9
--- a/src/java.base/share/classes/sun/nio/ch/SelectorImpl.java	Wed Oct 02 08:27:17 2019 +0200
+++ b/src/java.base/share/classes/sun/nio/ch/SelectorImpl.java	Wed Oct 02 09:16:18 2019 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -33,7 +33,9 @@
 import java.nio.channels.spi.AbstractSelectableChannel;
 import java.nio.channels.spi.AbstractSelector;
 import java.nio.channels.spi.SelectorProvider;
+import java.util.ArrayDeque;
 import java.util.Collections;
+import java.util.Deque;
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.Objects;
@@ -46,7 +48,7 @@
  * Base Selector implementation class.
  */
 
-abstract class SelectorImpl
+public abstract class SelectorImpl
     extends AbstractSelector
 {
     // The set of keys registered with this Selector
@@ -59,6 +61,9 @@
     private final Set<SelectionKey> publicKeys;             // Immutable
     private final Set<SelectionKey> publicSelectedKeys;     // Removal allowed, but not addition
 
+    // pending cancelled keys for deregistration
+    private final Deque<SelectionKeyImpl> cancelledKeys = new ArrayDeque<>();
+
     // used to check for reentrancy
     private boolean inSelect;
 
@@ -239,33 +244,36 @@
     protected abstract void implDereg(SelectionKeyImpl ski) throws IOException;
 
     /**
-     * Invoked by selection operations to process the cancelled-key set
+     * Queue a cancelled key for the next selection operation
+     */
+    public void cancel(SelectionKeyImpl ski) {
+        synchronized (cancelledKeys) {
+            cancelledKeys.addLast(ski);
+        }
+    }
+
+    /**
+     * Invoked by selection operations to process the cancelled keys
      */
     protected final void processDeregisterQueue() throws IOException {
         assert Thread.holdsLock(this);
         assert Thread.holdsLock(publicSelectedKeys);
 
-        Set<SelectionKey> cks = cancelledKeys();
-        synchronized (cks) {
-            if (!cks.isEmpty()) {
-                Iterator<SelectionKey> i = cks.iterator();
-                while (i.hasNext()) {
-                    SelectionKeyImpl ski = (SelectionKeyImpl)i.next();
-                    i.remove();
-
-                    // remove the key from the selector
-                    implDereg(ski);
+        synchronized (cancelledKeys) {
+            SelectionKeyImpl ski;
+            while ((ski = cancelledKeys.pollFirst()) != null) {
+                // remove the key from the selector
+                implDereg(ski);
 
-                    selectedKeys.remove(ski);
-                    keys.remove(ski);
+                selectedKeys.remove(ski);
+                keys.remove(ski);
 
-                    // remove from channel's key set
-                    deregister(ski);
+                // remove from channel's key set
+                deregister(ski);
 
-                    SelectableChannel ch = ski.channel();
-                    if (!ch.isOpen() && !ch.isRegistered())
-                        ((SelChImpl)ch).kill();
-                }
+                SelectableChannel ch = ski.channel();
+                if (!ch.isOpen() && !ch.isRegistered())
+                    ((SelChImpl)ch).kill();
             }
         }
     }