1/*
2 * Copyright (c) 2001, 2016, 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
26package sun.nio.ch;
27
28import java.io.IOException;
29import java.nio.channels.*;
30import java.nio.channels.spi.*;
31import java.util.*;
32
33
34/**
35 * An implementation of Selector for Solaris.
36 */
37
38class PollSelectorImpl
39    extends AbstractPollSelectorImpl
40{
41
42    // File descriptors used for interrupt
43    private int fd0;
44    private int fd1;
45
46    // Lock for interrupt triggering and clearing
47    private Object interruptLock = new Object();
48    private boolean interruptTriggered = false;
49
50    /**
51     * Package private constructor called by factory method in
52     * the abstract superclass Selector.
53     */
54    PollSelectorImpl(SelectorProvider sp) {
55        super(sp, 1, 1);
56        long pipeFds = IOUtil.makePipe(false);
57        fd0 = (int) (pipeFds >>> 32);
58        fd1 = (int) pipeFds;
59        try {
60            pollWrapper = new PollArrayWrapper(INIT_CAP);
61            pollWrapper.initInterrupt(fd0, fd1);
62            channelArray = new SelectionKeyImpl[INIT_CAP];
63        } catch (Throwable t) {
64            try {
65                FileDispatcherImpl.closeIntFD(fd0);
66            } catch (IOException ioe0) {
67                t.addSuppressed(ioe0);
68            }
69            try {
70                FileDispatcherImpl.closeIntFD(fd1);
71            } catch (IOException ioe1) {
72                t.addSuppressed(ioe1);
73            }
74            throw t;
75        }
76    }
77
78    protected int doSelect(long timeout)
79        throws IOException
80    {
81        if (channelArray == null)
82            throw new ClosedSelectorException();
83        processDeregisterQueue();
84        try {
85            begin();
86            pollWrapper.poll(totalChannels, 0, timeout);
87        } finally {
88            end();
89        }
90        processDeregisterQueue();
91        int numKeysUpdated = updateSelectedKeys();
92        if (pollWrapper.getReventOps(0) != 0) {
93            // Clear the wakeup pipe
94            pollWrapper.putReventOps(0, 0);
95            synchronized (interruptLock) {
96                IOUtil.drain(fd0);
97                interruptTriggered = false;
98            }
99        }
100        return numKeysUpdated;
101    }
102
103    protected void implCloseInterrupt() throws IOException {
104        // prevent further wakeup
105        synchronized (interruptLock) {
106            interruptTriggered = true;
107        }
108        FileDispatcherImpl.closeIntFD(fd0);
109        FileDispatcherImpl.closeIntFD(fd1);
110        fd0 = -1;
111        fd1 = -1;
112        pollWrapper.release(0);
113    }
114
115    public Selector wakeup() {
116        synchronized (interruptLock) {
117            if (!interruptTriggered) {
118                pollWrapper.interrupt();
119                interruptTriggered = true;
120            }
121        }
122        return this;
123    }
124
125}
126