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 final int ringEntries;
45 final int ringCapacity;
46
47 private final int ringMask;
48 private int ringHead;
49
50 CompletionQueue(long kHeadAddress, long kTailAddress, long kRingMaskAddress, long kRingEntriesAddress,
51 long kOverflowAddress, long completionQueueArrayAddress, int ringSize, long ringAddress,
52 int ringFd, int ringCapacity) {
53 this.kHeadAddress = kHeadAddress;
54 this.kTailAddress = kTailAddress;
55 this.completionQueueArrayAddress = completionQueueArrayAddress;
56 this.ringSize = ringSize;
57 this.ringAddress = ringAddress;
58 this.ringFd = ringFd;
59 this.ringCapacity = ringCapacity;
60
61 ringEntries = PlatformDependent.getIntVolatile(kRingEntriesAddress);
62 ringMask = PlatformDependent.getIntVolatile(kRingMaskAddress);
63 ringHead = PlatformDependent.getIntVolatile(kHeadAddress);
64 }
65
66
67
68
69
70 boolean hasCompletions() {
71 return ringHead != PlatformDependent.getIntVolatile(kTailAddress);
72 }
73
74 int count() {
75 return PlatformDependent.getIntVolatile(kTailAddress) - ringHead;
76 }
77
78
79
80
81
82 int process(CompletionCallback callback) {
83 int tail = PlatformDependent.getIntVolatile(kTailAddress);
84 try {
85 int i = 0;
86 while (ringHead != tail) {
87 long cqeAddress = completionQueueArrayAddress + (ringHead & ringMask) * CQE_SIZE;
88
89 long udata = PlatformDependent.getLong(cqeAddress + CQE_USER_DATA_FIELD);
90 int res = PlatformDependent.getInt(cqeAddress + CQE_RES_FIELD);
91 int flags = PlatformDependent.getInt(cqeAddress + CQE_FLAGS_FIELD);
92
93 ringHead++;
94
95 i++;
96 if (!callback.handle(res, flags, udata)) {
97
98 break;
99 }
100 }
101 return i;
102 } finally {
103
104 PlatformDependent.putIntOrdered(kHeadAddress, ringHead);
105 }
106 }
107
108 @Override
109 public String toString() {
110 StringJoiner sb = new StringJoiner(", ", "CompletionQueue [", "]");
111 int tail = PlatformDependent.getIntVolatile(kTailAddress);
112 int head = ringHead;
113 while (head != tail) {
114 long cqeAddress = completionQueueArrayAddress + (ringHead & ringMask) * CQE_SIZE;
115 long udata = PlatformDependent.getLong(cqeAddress + CQE_USER_DATA_FIELD);
116 int res = PlatformDependent.getInt(cqeAddress + CQE_RES_FIELD);
117 int flags = PlatformDependent.getInt(cqeAddress + CQE_FLAGS_FIELD);
118
119 sb.add("(res=" + res).add(", flags=" + flags).add(", udata=" + udata).add(")");
120 head++;
121 }
122 return sb.toString();
123 }
124 }