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.IllegalReferenceCountException;
20
21 import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
22
23 import static io.netty.util.internal.ObjectUtil.checkPositive;
24
25
26
27
28 public abstract class AbstractReferenceCountedByteBuf extends AbstractByteBuf {
29
30 private static final AtomicIntegerFieldUpdater<AbstractReferenceCountedByteBuf> refCntUpdater =
31 AtomicIntegerFieldUpdater.newUpdater(AbstractReferenceCountedByteBuf.class, "refCnt");
32
33 private volatile int refCnt;
34
35 protected AbstractReferenceCountedByteBuf(int maxCapacity) {
36 super(maxCapacity);
37 refCntUpdater.set(this, 1);
38 }
39
40 @Override
41 public int refCnt() {
42 return refCnt;
43 }
44
45
46
47
48 protected final void setRefCnt(int refCnt) {
49 refCntUpdater.set(this, refCnt);
50 }
51
52 @Override
53 public ByteBuf retain() {
54 return retain0(1);
55 }
56
57 @Override
58 public ByteBuf retain(int increment) {
59 return retain0(checkPositive(increment, "increment"));
60 }
61
62 private ByteBuf retain0(final int increment) {
63 int oldRef = refCntUpdater.getAndAdd(this, increment);
64 if (oldRef <= 0 || oldRef + increment < oldRef) {
65
66 refCntUpdater.getAndAdd(this, -increment);
67 throw new IllegalReferenceCountException(oldRef, increment);
68 }
69 return this;
70 }
71
72 @Override
73 public boolean release() {
74 return release0(1);
75 }
76
77 @Override
78 public boolean release(int decrement) {
79 return release0(checkPositive(decrement, "decrement"));
80 }
81
82 private boolean release0(int decrement) {
83 int oldRef = refCntUpdater.getAndAdd(this, -decrement);
84 if (oldRef == decrement) {
85 deallocate();
86 return true;
87 } else if (oldRef < decrement || oldRef - decrement > oldRef) {
88
89 refCntUpdater.getAndAdd(this, decrement);
90 throw new IllegalReferenceCountException(oldRef, decrement);
91 }
92 return false;
93 }
94
95
96
97 protected abstract void deallocate();
98 }