1 /*
2  * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
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
7  * published by the Free Software Foundation.  Oracle designates this
8  * particular file as subject to the "Classpath" exception as provided
9  * by Oracle in the LICENSE file that accompanied this code.
10  *
11  * This code is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14  * version 2 for more details (a copy is included in the LICENSE file that
15  * accompanied this code).
16  *
17  * You should have received a copy of the GNU General Public License version
18  * 2 along with this work; if not, write to the Free Software Foundation,
19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20  *
21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22  * or visit www.oracle.com if you need additional information or have any
23  * questions.
24  */
25 
26 package sun.nio.ch;
27 
28 import java.io.IOException;
29 import java.nio.channels.*;
30 import java.nio.channels.spi.*;
31 import java.net.SocketException;
32 import java.util.*;
33 
34 
35 /**
36  * Base Selector implementation class.
37  */
38 
39 public abstract class SelectorImpl
40     extends AbstractSelector
41 {
42 
43     // The set of keys with data ready for an operation
44     protected Set<SelectionKey> selectedKeys;
45 
46     // The set of keys registered with this Selector
47     protected HashSet<SelectionKey> keys;
48 
49     // Public views of the key sets
50     private Set<SelectionKey> publicKeys;             // Immutable
51     private Set<SelectionKey> publicSelectedKeys;     // Removal allowed, but not addition
52 
SelectorImpl(SelectorProvider sp)53     protected SelectorImpl(SelectorProvider sp) {
54         super(sp);
55         keys = new HashSet<SelectionKey>();
56         selectedKeys = new HashSet<SelectionKey>();
57         if (Util.atBugLevel("1.4")) {
58             publicKeys = keys;
59             publicSelectedKeys = selectedKeys;
60         } else {
61             publicKeys = Collections.unmodifiableSet(keys);
62             publicSelectedKeys = Util.ungrowableSet(selectedKeys);
63         }
64     }
65 
keys()66     public Set<SelectionKey> keys() {
67         if (!isOpen() && !Util.atBugLevel("1.4"))
68             throw new ClosedSelectorException();
69         return publicKeys;
70     }
71 
selectedKeys()72     public Set<SelectionKey> selectedKeys() {
73         if (!isOpen() && !Util.atBugLevel("1.4"))
74             throw new ClosedSelectorException();
75         return publicSelectedKeys;
76     }
77 
doSelect(long timeout)78     protected abstract int doSelect(long timeout) throws IOException;
79 
lockAndDoSelect(long timeout)80     private int lockAndDoSelect(long timeout) throws IOException {
81         synchronized (this) {
82             if (!isOpen())
83                 throw new ClosedSelectorException();
84             synchronized (publicKeys) {
85                 synchronized (publicSelectedKeys) {
86                     return doSelect(timeout);
87                 }
88             }
89         }
90     }
91 
select(long timeout)92     public int select(long timeout)
93         throws IOException
94     {
95         if (timeout < 0)
96             throw new IllegalArgumentException("Negative timeout");
97         return lockAndDoSelect((timeout == 0) ? -1 : timeout);
98     }
99 
select()100     public int select() throws IOException {
101         return select(0);
102     }
103 
selectNow()104     public int selectNow() throws IOException {
105         return lockAndDoSelect(0);
106     }
107 
implCloseSelector()108     public void implCloseSelector() throws IOException {
109         wakeup();
110         synchronized (this) {
111             synchronized (publicKeys) {
112                 synchronized (publicSelectedKeys) {
113                     implClose();
114                 }
115             }
116         }
117     }
118 
implClose()119     protected abstract void implClose() throws IOException;
120 
putEventOps(SelectionKeyImpl sk, int ops)121     public void putEventOps(SelectionKeyImpl sk, int ops) { }
122 
register(AbstractSelectableChannel ch, int ops, Object attachment)123     protected final SelectionKey register(AbstractSelectableChannel ch,
124                                           int ops,
125                                           Object attachment)
126     {
127         if (!(ch instanceof SelChImpl))
128             throw new IllegalSelectorException();
129         SelectionKeyImpl k = new SelectionKeyImpl((SelChImpl)ch, this);
130         k.attach(attachment);
131         synchronized (publicKeys) {
132             implRegister(k);
133         }
134         k.interestOps(ops);
135         return k;
136     }
137 
implRegister(SelectionKeyImpl ski)138     protected abstract void implRegister(SelectionKeyImpl ski);
139 
processDeregisterQueue()140     void processDeregisterQueue() throws IOException {
141         // Precondition: Synchronized on this, keys, and selectedKeys
142         Set<SelectionKey> cks = cancelledKeys();
143         synchronized (cks) {
144             if (!cks.isEmpty()) {
145                 Iterator<SelectionKey> i = cks.iterator();
146                 while (i.hasNext()) {
147                     SelectionKeyImpl ski = (SelectionKeyImpl)i.next();
148                     try {
149                         implDereg(ski);
150                     } catch (SocketException se) {
151                         throw new IOException("Error deregistering key", se);
152                     } finally {
153                         i.remove();
154                     }
155                 }
156             }
157         }
158     }
159 
implDereg(SelectionKeyImpl ski)160     protected abstract void implDereg(SelectionKeyImpl ski) throws IOException;
161 
wakeup()162     abstract public Selector wakeup();
163 
164 }
165