View Javadoc
1   /*
2    * Copyright 2016 The Netty Project
3    *
4    * The Netty Project licenses this file to you under the Apache License,
5    * version 2.0 (the "License"); you may not use this file except in compliance
6    * with the License. You may obtain a copy of the License at:
7    *
8    *   https://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13   * License for the specific language governing permissions and limitations
14   * under the License.
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  import static io.netty.channel.unix.Limits.SIZEOF_JLONG;
24  import static io.netty.util.internal.ObjectUtil.checkPositive;
25  
26  final class NativeLongArray {
27      private ByteBuffer memory;
28      private long memoryAddress;
29      private int capacity;
30      private int size;
31  
32      NativeLongArray(int capacity) {
33          this.capacity = checkPositive(capacity, "capacity");
34          memory = Buffer.allocateDirectWithNativeOrder(calculateBufferCapacity(capacity));
35          memoryAddress = Buffer.memoryAddress(memory);
36      }
37  
38      private static int idx(int index) {
39          return index * SIZEOF_JLONG;
40      }
41  
42      private static int calculateBufferCapacity(int capacity) {
43          return capacity * SIZEOF_JLONG;
44      }
45  
46      void add(long value) {
47          reallocIfNeeded();
48          if (PlatformDependent.hasUnsafe()) {
49              PlatformDependent.putLong(memoryOffset(size), value);
50          } else {
51              memory.putLong(idx(size), value);
52          }
53          ++size;
54      }
55  
56      void clear() {
57          size = 0;
58      }
59  
60      boolean isEmpty() {
61          return size == 0;
62      }
63  
64      int size() {
65          return size;
66      }
67  
68      void free() {
69          Buffer.free(memory);
70          memoryAddress = 0;
71      }
72  
73      long memoryAddress() {
74          return memoryAddress;
75      }
76  
77      long memoryAddressEnd() {
78          return memoryOffset(size);
79      }
80  
81      private long memoryOffset(int index) {
82          return memoryAddress + idx(index);
83      }
84  
85      private void reallocIfNeeded() {
86          if (size == capacity) {
87              // Double the capacity while it is "sufficiently small", and otherwise increase by 50%.
88              int newLength = capacity <= 65536 ? capacity << 1 : capacity + capacity >> 1;
89              ByteBuffer buffer = Buffer.allocateDirectWithNativeOrder(calculateBufferCapacity(newLength));
90              // Copy over the old content of the memory and reset the position as we always act on the buffer as if
91              // the position was never increased.
92              memory.position(0).limit(size);
93              buffer.put(memory);
94              buffer.position(0);
95  
96              Buffer.free(memory);
97              memory = buffer;
98              memoryAddress = Buffer.memoryAddress(buffer);
99              capacity = newLength;
100         }
101     }
102 
103     @Override
104     public String toString() {
105         return "memoryAddress: " + memoryAddress + " capacity: " + capacity + " size: " + size;
106     }
107 }