1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package io.netty.buffer;
18
19 import io.netty.util.internal.StringUtil;
20
21 final class PoolChunkList<T> {
22 private final PoolArena<T> arena;
23 private final PoolChunkList<T> nextList;
24 PoolChunkList<T> prevList;
25
26 private final int minUsage;
27 private final int maxUsage;
28
29 private PoolChunk<T> head;
30
31
32
33
34 PoolChunkList(PoolArena<T> arena, PoolChunkList<T> nextList, int minUsage, int maxUsage) {
35 this.arena = arena;
36 this.nextList = nextList;
37 this.minUsage = minUsage;
38 this.maxUsage = maxUsage;
39 }
40
41 boolean allocate(PooledByteBuf<T> buf, int reqCapacity, int normCapacity) {
42 if (head == null) {
43 return false;
44 }
45
46 for (PoolChunk<T> cur = head;;) {
47 long handle = cur.allocate(normCapacity);
48 if (handle < 0) {
49 cur = cur.next;
50 if (cur == null) {
51 return false;
52 }
53 } else {
54 cur.initBuf(buf, handle, reqCapacity);
55 if (cur.usage() >= maxUsage) {
56 remove(cur);
57 nextList.add(cur);
58 }
59 return true;
60 }
61 }
62 }
63
64 void free(PoolChunk<T> chunk, long handle) {
65 chunk.free(handle);
66 if (chunk.usage() < minUsage) {
67 remove(chunk);
68 if (prevList == null) {
69 assert chunk.usage() == 0;
70 arena.destroyChunk(chunk);
71 } else {
72 prevList.add(chunk);
73 }
74 }
75 }
76
77 void add(PoolChunk<T> chunk) {
78 if (chunk.usage() >= maxUsage) {
79 nextList.add(chunk);
80 return;
81 }
82
83 chunk.parent = this;
84 if (head == null) {
85 head = chunk;
86 chunk.prev = null;
87 chunk.next = null;
88 } else {
89 chunk.prev = null;
90 chunk.next = head;
91 head.prev = chunk;
92 head = chunk;
93 }
94 }
95
96 private void remove(PoolChunk<T> cur) {
97 if (cur == head) {
98 head = cur.next;
99 if (head != null) {
100 head.prev = null;
101 }
102 } else {
103 PoolChunk<T> next = cur.next;
104 cur.prev.next = next;
105 if (next != null) {
106 next.prev = cur.prev;
107 }
108 }
109 }
110
111 @Override
112 public String toString() {
113 if (head == null) {
114 return "none";
115 }
116
117 StringBuilder buf = new StringBuilder();
118 for (PoolChunk<T> cur = head;;) {
119 buf.append(cur);
120 cur = cur.next;
121 if (cur == null) {
122 break;
123 }
124 buf.append(StringUtil.NEWLINE);
125 }
126
127 return buf.toString();
128 }
129 }