1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package io.netty.channel.uring;
17
18 import io.netty.util.internal.PlatformDependent;
19
20 import java.util.StringJoiner;
21
22
23
24
25 final class CompletionQueue {
26
27
28
29 private static final int CQE_USER_DATA_FIELD = 0;
30 private static final int CQE_RES_FIELD = 8;
31 private static final int CQE_FLAGS_FIELD = 12;
32
33 private static final long CQE_SIZE = 16;
34
35
36 private final long kHeadAddress;
37 private final long kTailAddress;
38
39 private final long completionQueueArrayAddress;
40
41 final int ringSize;
42 final long ringAddress;
43 final int ringFd;
44
45 private final int ringEntries;
46 private final int ringMask;
47 private int ringHead;
48
49 CompletionQueue(long kHeadAddress, long kTailAddress, long kRingMaskAddress, long kRingEntriesAddress,
50 long kOverflowAddress, long completionQueueArrayAddress, int ringSize, long ringAddress,
51 int ringFd) {
52 this.kHeadAddress = kHeadAddress;
53 this.kTailAddress = kTailAddress;
54 this.completionQueueArrayAddress = completionQueueArrayAddress;
55 this.ringSize = ringSize;
56 this.ringAddress = ringAddress;
57 this.ringFd = ringFd;
58
59 ringEntries = PlatformDependent.getIntVolatile(kRingEntriesAddress);
60 ringMask = PlatformDependent.getIntVolatile(kRingMaskAddress);
61 ringHead = PlatformDependent.getIntVolatile(kHeadAddress);
62 }
63
64
65
66
67
68 boolean hasCompletions() {
69 return ringHead != PlatformDependent.getIntVolatile(kTailAddress);
70 }
71
72 int count() {
73 return PlatformDependent.getIntVolatile(kTailAddress) - ringHead;
74 }
75
76
77
78
79
80 int process(CompletionCallback callback) {
81 int tail = PlatformDependent.getIntVolatile(kTailAddress);
82 int i = 0;
83 while (ringHead != tail) {
84 long cqeAddress = completionQueueArrayAddress + (ringHead & ringMask) * CQE_SIZE;
85
86 long udata = PlatformDependent.getLong(cqeAddress + CQE_USER_DATA_FIELD);
87 int res = PlatformDependent.getInt(cqeAddress + CQE_RES_FIELD);
88 int flags = PlatformDependent.getInt(cqeAddress + CQE_FLAGS_FIELD);
89
90
91 ringHead++;
92 PlatformDependent.putIntOrdered(kHeadAddress, ringHead);
93
94 i++;
95 if (!callback.handle(res, flags, udata)) {
96
97 break;
98 }
99 }
100 return i;
101 }
102
103 @Override
104 public String toString() {
105 StringJoiner sb = new StringJoiner(", ", "CompletionQueue [", "]");
106 int tail = PlatformDependent.getIntVolatile(kTailAddress);
107 int head = ringHead;
108 while (head != tail) {
109 long cqeAddress = completionQueueArrayAddress + (ringHead & ringMask) * CQE_SIZE;
110 long udata = PlatformDependent.getLong(cqeAddress + CQE_USER_DATA_FIELD);
111 int res = PlatformDependent.getInt(cqeAddress + CQE_RES_FIELD);
112 int flags = PlatformDependent.getInt(cqeAddress + CQE_FLAGS_FIELD);
113
114 sb.add("(res=" + res).add(", flags=" + flags).add(", udata=" + udata).add(")");
115 head++;
116 }
117 return sb.toString();
118 }
119 }