NIO之PollArrayWrapper(轮询数组包装器)(主要用于对FD文件描述符和events事件掩码操作)

2023-09-05 11:28:13 浏览数 (2)

PollArrayWrapper创建流程PollArrayWrapper创建流程
代码语言:javascript复制
// 创建轮询数组包装器
/**
 * typedef struct pollfd {
 *    SOCKET fd;            // 4 bytes
 *    short events;         // 2 bytes
 * } pollfd_t;
 */
pollWrapper = new PollArrayWrapper(INIT_CAP);
代码语言:javascript复制
PollArrayWrapper(int newSize) {
    int allocationSize = newSize * SIZE_POLLFD;
    // 给轮询数组分配本地对象(分配内存)
    pollArray = new AllocatedNativeObject(allocationSize, true);
    pollArrayAddress = pollArray.address();
    this.size = newSize;
}
代码语言:javascript复制
// 本地对象(内存对象)
protected NativeObject(int size, boolean pageAligned) {
    if (!pageAligned) {
        this.allocationAddress = unsafe.allocateMemory(size);
        this.address = this.allocationAddress;
    } else {
        int ps = pageSize();
        // 使用非安全操作工具, 直接分配JAVA堆外内存
        long a = unsafe.allocateMemory(size   ps);
        this.allocationAddress = a;
        // 使用位运算& 进行页对齐
        this.address = a   ps - (a & (ps - 1));
    }
}

pollArray添加需要唤醒的Socket

轮询数组添加需要唤醒(监听)的Socket轮询数组添加需要唤醒(监听)的Socket
代码语言:javascript复制
// 添加需要唤醒的文件描述符
pollWrapper.addWakeupSocket(wakeupSourceFd, 0);
代码语言:javascript复制
// 添加文件描述符
void addWakeupSocket(int fdVal, int index) {
    // 在特定位置index, PUT文件描述符
    putDescriptor(index, fdVal);
    // 在特定位置index, PUT事件类型(POLLIN 代表:普通数据读取)
    putEventOps(index, Net.POLLIN);
}

 void putDescriptor(int i, int fd) {
    // 根据index下标位和偏移量, 计算要PUT fd到的内存位置
    pollArray.putInt(SIZE_POLLFD * i   FD_OFFSET, fd);
}

void putEventOps(int i, int event) {
    // 根据index下标位和偏移量, 计算要PUT event到的内存位置
    pollArray.putShort(SIZE_POLLFD * i   EVENT_OFFSET, (short)event);
}

0 人点赞