Callback Based Selectors

David Lloyd david.lloyd at redhat.com
Wed Mar 28 18:22:57 UTC 2018


On Wed, Mar 28, 2018 at 12:09 PM, Alan Bateman <Alan.Bateman at oracle.com> wrote:
> On 28/03/2018 15:45, David Lloyd wrote:
>>
>> :
>> I wonder, since we're moving these APIs to be more
>> concurrency-friendly, if you could consider an additional small
>> enhancement to add a couple atomic operations to SelectionKey for
>> interest ops like getAndSetBits/getAndClearBits?  [...]
>
> interestOpsOr(int ops) and interestOpsAnd(int ops) wouldn't look out of
> place. It would be a good use of var handles as you could implement it with
> something like:
> [...] So go ahead!

OK!  Here's a v1 pass which just includes the base methods on
SelectionKey (attached and [1]).

Unfortunately, it looks like some nontrivial surgery would be
necessary after all before these could be fully implemented with
atomics in a correct way, due to
sun.nio.ch.SelChImpl#translateAndSetInterestOps() being required for a
change to take full effect, so I can look again once your
nioInterestOps change is in.

BTW, it looks like nioInterestOps(int) is no longer called outside of
SelectionKey now; maybe it can/should be inlined into
sun.nio.ch.SelectionKeyImpl#interestOps(int)?

[1] https://github.com/dmlloyd/openjdk/commit/atomic-nio-ops-v1

-- 
- DML
-------------- next part --------------
commit a5552ce78a16d7db22a3d10d0ce4c013fd2414a3
Author: David M. Lloyd <david.lloyd at redhat.com>
Date:   Wed Mar 28 13:13:44 2018 -0500

    [JDK-0000000] Add atomic interest op methods to SelectionKey

diff --git a/src/java.base/share/classes/java/nio/channels/SelectionKey.java b/src/java.base/share/classes/java/nio/channels/SelectionKey.java
index 6af664fa96b..8983093ade2 100644
--- a/src/java.base/share/classes/java/nio/channels/SelectionKey.java
+++ b/src/java.base/share/classes/java/nio/channels/SelectionKey.java
@@ -196,6 +196,82 @@ public abstract class SelectionKey {
      */
     public abstract SelectionKey interestOps(int ops);
 
+    /**
+     * Atomically sets this key's interest set to bitwise union ("or") of the existing
+     * interest set and the given value. This method is guaranteed to be
+     * atomic with respect to other concurrent calls to this method or to
+     * {@link #interestOpsAnd(int)}.
+     *
+     * <p> This method may be invoked at any time.  Whether or not it blocks,
+     * and for how long, is implementation-dependent.
+     *
+     * @param  ops  The interest set to apply
+     *
+     * @return  The previous interest set
+     *
+     * @throws  IllegalArgumentException
+     *          If a bit in the resultant set does not correspond to an operation that
+     *          is supported by this key's channel, that is, if
+     *          {@code ((interestOps() | ops) & ~channel().validOps()) != 0}
+     *
+     * @throws  CancelledKeyException
+     *          If this key has been cancelled
+     *
+     * @implSpec The default implementation synchronizes on this {@code SelectionKey}
+     *           instance, calling {@link #interestOps()} and {@link #interestOps(int)}
+     *           in turn; subclasses should provide a better implementation if
+     *           possible (for example, using a
+     *           {@link java.lang.invoke.VarHandle VarHandle} may be appropriate).
+     */
+    public int interestOpsOr(int ops) {
+        synchronized (this) {
+            int oldVal = interestOps();
+            interestOps(oldVal | ops);
+            return oldVal;
+        }
+    }
+
+    /**
+     * Atomically sets this key's interest set to bitwise intersection ("and") of the
+     * existing interest set and the given value. This method is guaranteed to be
+     * atomic with respect to other concurrent calls to this method or to
+     * {@link #interestOpsOr(int)}.
+     *
+     * <p> This method may be invoked at any time.  Whether or not it blocks,
+     * and for how long, is implementation-dependent.
+     *
+     * @param  ops  The interest set to apply
+     *
+     * @return  The previous interest set
+     *
+     * @throws  IllegalArgumentException
+     *          If a bit in the resultant set does not correspond to an operation that
+     *          is supported by this key's channel, that is, if
+     *          {@code (interestOps() & ops & ~channel().validOps()) != 0}
+     *
+     * @throws  CancelledKeyException
+     *          If this key has been cancelled
+     *
+     * @apiNote The {@code ops} argument may contain bits which are not normally
+     *          allowed by this key's channel, allowing bits to be cleared using
+     *          bitwise complement values.  For example,
+     *          {@code interestOpsAnd(~SelectionKey.OP_READ)} will remove the
+     *          {@code OP_READ} bit from the set without affecting other bits.
+     *
+     * @implSpec The default implementation synchronizes on this {@code SelectionKey}
+     *           instance, calling {@link #interestOps()} and {@link #interestOps(int)}
+     *           in turn; subclasses should provide a better implementation if
+     *           possible (for example, using a
+     *           {@link java.lang.invoke.VarHandle VarHandle} may be appropriate).
+     */
+    public int interestOpsAnd(int ops) {
+        synchronized (this) {
+            int oldVal = interestOps();
+            interestOps(oldVal & ops);
+            return oldVal;
+        }
+    }
+
     /**
      * Retrieves this key's ready-operation set.
      *


More information about the nio-dev mailing list