1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package io.netty.channel.kqueue;
17
18 import io.netty.channel.unix.Buffer;
19 import io.netty.util.internal.PlatformDependent;
20
21 import java.nio.ByteBuffer;
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37 final class KQueueEventArray {
38 private static final int KQUEUE_EVENT_SIZE = Native.sizeofKEvent();
39 private static final int KQUEUE_IDENT_OFFSET = Native.offsetofKEventIdent();
40 private static final int KQUEUE_FILTER_OFFSET = Native.offsetofKEventFilter();
41 private static final int KQUEUE_FFLAGS_OFFSET = Native.offsetofKEventFFlags();
42 private static final int KQUEUE_FLAGS_OFFSET = Native.offsetofKEventFlags();
43 private static final int KQUEUE_DATA_OFFSET = Native.offsetofKeventData();
44 private static final int KQUEUE_UDATA_OFFSET = Native.offsetofKeventUdata();
45
46 private ByteBuffer memory;
47 private long memoryAddress;
48 private int size;
49 private int capacity;
50
51 KQueueEventArray(int capacity) {
52 if (capacity < 1) {
53 throw new IllegalArgumentException("capacity must be >= 1 but was " + capacity);
54 }
55 memory = Buffer.allocateDirectWithNativeOrder(calculateBufferCapacity(capacity));
56 memoryAddress = Buffer.memoryAddress(memory);
57 this.capacity = capacity;
58 }
59
60
61
62
63 long memoryAddress() {
64 return memoryAddress;
65 }
66
67
68
69
70
71 int capacity() {
72 return capacity;
73 }
74
75 int size() {
76 return size;
77 }
78
79 void clear() {
80 size = 0;
81 }
82
83 void evSet(int ident, short filter, short flags, int fflags, long data, long udata) {
84 reallocIfNeeded();
85 evSet(getKEventOffset(size++) + memoryAddress, ident, filter, flags,
86 fflags, data, udata);
87 }
88
89 private void reallocIfNeeded() {
90 if (size == capacity) {
91 realloc(true);
92 }
93 }
94
95
96
97
98 void realloc(boolean throwIfFail) {
99
100 int newLength = capacity <= 65536 ? capacity << 1 : capacity + capacity >> 1;
101
102 try {
103 ByteBuffer buffer = Buffer.allocateDirectWithNativeOrder(calculateBufferCapacity(newLength));
104
105
106 memory.position(0).limit(size);
107 buffer.put(memory);
108 buffer.position(0);
109
110 Buffer.free(memory);
111 memory = buffer;
112 memoryAddress = Buffer.memoryAddress(buffer);
113 } catch (OutOfMemoryError e) {
114 if (throwIfFail) {
115 OutOfMemoryError error = new OutOfMemoryError(
116 "unable to allocate " + newLength + " new bytes! Existing capacity is: " + capacity);
117 error.initCause(e);
118 throw error;
119 }
120 }
121 }
122
123
124
125
126 void free() {
127 Buffer.free(memory);
128 memoryAddress = size = capacity = 0;
129 }
130
131 private static int getKEventOffset(int index) {
132 return index * KQUEUE_EVENT_SIZE;
133 }
134
135 private long getKEventOffsetAddress(int index) {
136 return getKEventOffset(index) + memoryAddress;
137 }
138
139 private short getShort(int index, int offset) {
140 if (PlatformDependent.hasUnsafe()) {
141 return PlatformDependent.getShort(getKEventOffsetAddress(index) + offset);
142 }
143 return memory.getShort(getKEventOffset(index) + offset);
144 }
145
146 short flags(int index) {
147 return getShort(index, KQUEUE_FLAGS_OFFSET);
148 }
149
150 short filter(int index) {
151 return getShort(index, KQUEUE_FILTER_OFFSET);
152 }
153
154 short fflags(int index) {
155 return getShort(index, KQUEUE_FFLAGS_OFFSET);
156 }
157
158 int fd(int index) {
159 if (PlatformDependent.hasUnsafe()) {
160 return PlatformDependent.getInt(getKEventOffsetAddress(index) + KQUEUE_IDENT_OFFSET);
161 }
162 return memory.getInt(getKEventOffset(index) + KQUEUE_IDENT_OFFSET);
163 }
164
165 long data(int index) {
166 return getLong(index, KQUEUE_DATA_OFFSET);
167 }
168
169 long udata(int index) {
170 return getLong(index, KQUEUE_UDATA_OFFSET);
171 }
172
173 private long getLong(int index, int offset) {
174 if (PlatformDependent.hasUnsafe()) {
175 return PlatformDependent.getLong(getKEventOffsetAddress(index) + offset);
176 }
177 return memory.getLong(getKEventOffset(index) + offset);
178 }
179
180 private static int calculateBufferCapacity(int capacity) {
181 return capacity * KQUEUE_EVENT_SIZE;
182 }
183
184 private static native void evSet(
185 long keventAddress, int ident, short filter, short flags, int fflags, long data, long udata);
186 }