View Javadoc
1   /*
2    * Copyright 2015 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    *   http://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.epoll;
17  
18  import io.netty.util.internal.PlatformDependent;
19  
20  /**
21   * This is an internal datastructure which can be directly passed to epoll_wait to reduce the overhead.
22   *
23   * typedef union epoll_data {
24   *     void        *ptr;
25   *     int          fd;
26   *     uint32_t     u32;
27   *     uint64_t     u64;
28   * } epoll_data_t;
29   *
30   * struct epoll_event {
31   *     uint32_t     events;      // Epoll events
32   *     epoll_data_t data;        // User data variable
33   * };
34   *
35   * We use {@code fd} if the {@code epoll_data union} to store the actual file descriptor of an
36   * {@link AbstractEpollChannel} and so be able to map it later.
37   */
38  final class EpollEventArray {
39      // Size of the epoll_event struct
40      private static final int EPOLL_EVENT_SIZE = Native.sizeofEpollEvent();
41      // The offsiet of the data union in the epoll_event struct
42      private static final int EPOLL_DATA_OFFSET = Native.offsetofEpollData();
43  
44      private long memoryAddress;
45      private int length;
46  
47      EpollEventArray(int length) {
48          if (length < 1) {
49              throw new IllegalArgumentException("length must be >= 1 but was " + length);
50          }
51          this.length = length;
52          memoryAddress = allocate(length);
53      }
54  
55      private static long allocate(int length) {
56          return PlatformDependent.allocateMemory(length * EPOLL_EVENT_SIZE);
57      }
58  
59      /**
60       * Return the {@code memoryAddress} which points to the start of this {@link EpollEventArray}.
61       */
62      long memoryAddress() {
63          return memoryAddress;
64      }
65  
66      /**
67       * Return the length of the {@link EpollEventArray} which represent the maximum number of {@code epoll_events}
68       * that can be stored in it.
69       */
70      int length() {
71          return length;
72      }
73  
74      /**
75       * Increase the storage of this {@link EpollEventArray}.
76       */
77      void increase() {
78          // double the size
79          length <<= 1;
80          free();
81          memoryAddress = allocate(length);
82      }
83  
84      /**
85       * Free this {@link EpollEventArray}. Any usage after calling this method may segfault the JVM!
86       */
87      void free() {
88          PlatformDependent.freeMemory(memoryAddress);
89      }
90  
91      /**
92       * Return the events for the {@code epoll_event} on this index.
93       */
94      int events(int index) {
95          return PlatformDependent.getInt(memoryAddress + index * EPOLL_EVENT_SIZE);
96      }
97  
98      /**
99       * Return the file descriptor for the {@code epoll_event} on this index.
100      */
101     int fd(int index) {
102         return PlatformDependent.getInt(memoryAddress + index * EPOLL_EVENT_SIZE + EPOLL_DATA_OFFSET);
103     }
104 }