1 /*
2  * Copyright (c) 2001, 2018, 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 /*
27  */
28 
29 package sun.nio.ch;
30 
31 import java.lang.annotation.Native;
32 
33 /**
34  * Manipulates a native array of structs corresponding to (fd, events) pairs.
35  *
36  * typedef struct pollfd {
37  *    SOCKET fd;            // 4 bytes
38  *    short events;         // 2 bytes
39  * } pollfd_t;
40  *
41  * @author Konstantin Kladko
42  * @author Mike McCloskey
43  */
44 
45 class PollArrayWrapper {
46 
47     private AllocatedNativeObject pollArray; // The fd array
48 
49     long pollArrayAddress; // pollArrayAddress
50 
51     @Native private static final short FD_OFFSET     = 0; // fd offset in pollfd
52     @Native private static final short EVENT_OFFSET  = 4; // events offset in pollfd
53 
54     static short SIZE_POLLFD = 8; // sizeof pollfd struct
55 
56     private int size; // Size of the pollArray
57 
PollArrayWrapper(int newSize)58     PollArrayWrapper(int newSize) {
59         int allocationSize = newSize * SIZE_POLLFD;
60         pollArray = new AllocatedNativeObject(allocationSize, true);
61         pollArrayAddress = pollArray.address();
62         this.size = newSize;
63     }
64 
65     // Prepare another pollfd struct for use.
putEntry(int index, SelectionKeyImpl ski)66     void putEntry(int index, SelectionKeyImpl ski) {
67         putDescriptor(index, ski.getFDVal());
68         putEventOps(index, 0);
69     }
70 
71     // Writes the pollfd entry from the source wrapper at the source index
72     // over the entry in the target wrapper at the target index.
replaceEntry(PollArrayWrapper source, int sindex, PollArrayWrapper target, int tindex)73     void replaceEntry(PollArrayWrapper source, int sindex,
74                                      PollArrayWrapper target, int tindex) {
75         target.putDescriptor(tindex, source.getDescriptor(sindex));
76         target.putEventOps(tindex, source.getEventOps(sindex));
77     }
78 
79     // Grows the pollfd array to new size
grow(int newSize)80     void grow(int newSize) {
81         PollArrayWrapper temp = new PollArrayWrapper(newSize);
82         for (int i = 0; i < size; i++)
83             replaceEntry(this, i, temp, i);
84         pollArray.free();
85         pollArray = temp.pollArray;
86         this.size = temp.size;
87         pollArrayAddress = pollArray.address();
88     }
89 
free()90     void free() {
91         pollArray.free();
92     }
93 
94     // Access methods for fd structures
putDescriptor(int i, int fd)95     void putDescriptor(int i, int fd) {
96         pollArray.putInt(SIZE_POLLFD * i + FD_OFFSET, fd);
97     }
98 
putEventOps(int i, int event)99     void putEventOps(int i, int event) {
100         pollArray.putShort(SIZE_POLLFD * i + EVENT_OFFSET, (short)event);
101     }
102 
getEventOps(int i)103     int getEventOps(int i) {
104         return pollArray.getShort(SIZE_POLLFD * i + EVENT_OFFSET);
105     }
106 
getDescriptor(int i)107     int getDescriptor(int i) {
108        return pollArray.getInt(SIZE_POLLFD * i + FD_OFFSET);
109     }
110 
111     // Adds Windows wakeup socket at a given index.
addWakeupSocket(int fdVal, int index)112     void addWakeupSocket(int fdVal, int index) {
113         putDescriptor(index, fdVal);
114         putEventOps(index, Net.POLLIN);
115     }
116 }
117