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, fflags, data, udata);
86 }
87
88 private void reallocIfNeeded() {
89 if (size == capacity) {
90 realloc(true);
91 }
92 }
93
94
95
96
97 void realloc(boolean throwIfFail) {
98
99 int newLength = capacity <= 65536 ? capacity << 1 : capacity + capacity >> 1;
100
101 try {
102 ByteBuffer buffer = Buffer.allocateDirectWithNativeOrder(calculateBufferCapacity(newLength));
103
104
105 memory.position(0).limit(size);
106 buffer.put(memory);
107 buffer.position(0);
108
109 Buffer.free(memory);
110 memory = buffer;
111 memoryAddress = Buffer.memoryAddress(buffer);
112 } catch (OutOfMemoryError e) {
113 if (throwIfFail) {
114 OutOfMemoryError error = new OutOfMemoryError(
115 "unable to allocate " + newLength + " new bytes! Existing capacity is: " + capacity);
116 error.initCause(e);
117 throw error;
118 }
119 }
120 }
121
122
123
124
125 void free() {
126 Buffer.free(memory);
127 memoryAddress = size = capacity = 0;
128 }
129
130 private static int getKEventOffset(int index) {
131 return index * KQUEUE_EVENT_SIZE;
132 }
133
134 private long getKEventOffsetAddress(int index) {
135 return getKEventOffset(index) + memoryAddress;
136 }
137
138 private short getShort(int index, int offset) {
139 if (PlatformDependent.hasUnsafe()) {
140 return PlatformDependent.getShort(getKEventOffsetAddress(index) + offset);
141 }
142 return memory.getShort(getKEventOffset(index) + offset);
143 }
144
145 short flags(int index) {
146 return getShort(index, KQUEUE_FLAGS_OFFSET);
147 }
148
149 short filter(int index) {
150 return getShort(index, KQUEUE_FILTER_OFFSET);
151 }
152
153 short fflags(int index) {
154 return getShort(index, KQUEUE_FFLAGS_OFFSET);
155 }
156
157 int ident(int index) {
158 if (PlatformDependent.hasUnsafe()) {
159 return PlatformDependent.getInt(getKEventOffsetAddress(index) + KQUEUE_IDENT_OFFSET);
160 }
161 return memory.getInt(getKEventOffset(index) + KQUEUE_IDENT_OFFSET);
162 }
163
164 long data(int index) {
165 return getLong(index, KQUEUE_DATA_OFFSET);
166 }
167
168 long udata(int index) {
169 return getLong(index, KQUEUE_UDATA_OFFSET);
170 }
171
172 private long getLong(int index, int offset) {
173 if (PlatformDependent.hasUnsafe()) {
174 return PlatformDependent.getLong(getKEventOffsetAddress(index) + offset);
175 }
176 return memory.getLong(getKEventOffset(index) + offset);
177 }
178
179 private static int calculateBufferCapacity(int capacity) {
180 return capacity * KQUEUE_EVENT_SIZE;
181 }
182
183 private static native void evSet(
184 long keventAddress, int ident, short filter, short flags, int fflags, long data, long udata);
185 }