1 /* |
1 /* |
2 * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. |
2 * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * |
4 * |
5 * This code is free software; you can redistribute it and/or modify it |
5 * This code is free software; you can redistribute it and/or modify it |
6 * under the terms of the GNU General Public License version 2 only, as |
6 * under the terms of the GNU General Public License version 2 only, as |
7 * published by the Free Software Foundation. Oracle designates this |
7 * published by the Free Software Foundation. Oracle designates this |
23 * questions. |
23 * questions. |
24 */ |
24 */ |
25 |
25 |
26 package java.nio.channels.spi; |
26 package java.nio.channels.spi; |
27 |
27 |
28 import java.nio.channels.*; |
28 import java.lang.invoke.MethodHandles; |
|
29 import java.lang.invoke.VarHandle; |
|
30 import java.nio.channels.SelectionKey; |
|
31 import java.nio.channels.Selector; |
29 |
32 |
|
33 import sun.nio.ch.SelectionKeyImpl; |
|
34 import sun.nio.ch.SelectorImpl; |
30 |
35 |
31 /** |
36 /** |
32 * Base implementation class for selection keys. |
37 * Base implementation class for selection keys. |
33 * |
38 * |
34 * <p> This class tracks the validity of the key and implements cancellation. |
39 * <p> This class tracks the validity of the key and implements cancellation. |
39 */ |
44 */ |
40 |
45 |
41 public abstract class AbstractSelectionKey |
46 public abstract class AbstractSelectionKey |
42 extends SelectionKey |
47 extends SelectionKey |
43 { |
48 { |
|
49 private static final VarHandle INVALID; |
|
50 static { |
|
51 try { |
|
52 MethodHandles.Lookup l = MethodHandles.lookup(); |
|
53 INVALID = l.findVarHandle(AbstractSelectionKey.class, "invalid", boolean.class); |
|
54 } catch (Exception e) { |
|
55 throw new InternalError(e); |
|
56 } |
|
57 } |
44 |
58 |
45 /** |
59 /** |
46 * Initializes a new instance of this class. |
60 * Initializes a new instance of this class. |
47 */ |
61 */ |
48 protected AbstractSelectionKey() { } |
62 protected AbstractSelectionKey() { } |
49 |
63 |
50 private volatile boolean valid = true; |
64 private volatile boolean invalid; |
51 |
65 |
52 public final boolean isValid() { |
66 public final boolean isValid() { |
53 return valid; |
67 return !invalid; |
54 } |
68 } |
55 |
69 |
56 void invalidate() { // package-private |
70 void invalidate() { // package-private |
57 valid = false; |
71 invalid = true; |
58 } |
72 } |
59 |
73 |
60 /** |
74 /** |
61 * Cancels this key. |
75 * Cancels this key. |
62 * |
76 * |
63 * <p> If this key has not yet been cancelled then it is added to its |
77 * <p> If this key has not yet been cancelled then it is added to its |
64 * selector's cancelled-key set while synchronized on that set. </p> |
78 * selector's cancelled-key set while synchronized on that set. </p> |
65 */ |
79 */ |
66 public final void cancel() { |
80 public final void cancel() { |
67 // Synchronizing "this" to prevent this key from getting canceled |
81 boolean changed = (boolean) INVALID.compareAndSet(this, false, true); |
68 // multiple times by different threads, which might cause race |
82 if (changed) { |
69 // condition between selector's select() and channel's close(). |
83 Selector sel = selector(); |
70 synchronized (this) { |
84 if (sel instanceof SelectorImpl) { |
71 if (valid) { |
85 // queue cancelled key directly |
72 valid = false; |
86 ((SelectorImpl) sel).cancel((SelectionKeyImpl) this); |
73 ((AbstractSelector)selector()).cancel(this); |
87 } else { |
|
88 ((AbstractSelector) sel).cancel(this); |
74 } |
89 } |
75 } |
90 } |
76 } |
91 } |
77 } |
92 } |