1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package io.netty.buffer;
18
19 import java.lang.invoke.MethodHandles;
20 import java.lang.invoke.VarHandle;
21 import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
22
23 import io.netty.util.internal.AtomicReferenceCountUpdater;
24 import io.netty.util.internal.PlatformDependent;
25 import io.netty.util.internal.ReferenceCountUpdater;
26 import io.netty.util.internal.UnsafeReferenceCountUpdater;
27 import io.netty.util.internal.VarHandleReferenceCountUpdater;
28
29 import static io.netty.util.internal.ReferenceCountUpdater.getUnsafeOffset;
30 import static java.util.concurrent.atomic.AtomicIntegerFieldUpdater.newUpdater;
31
32
33
34
35 public abstract class AbstractReferenceCountedByteBuf extends AbstractByteBuf {
36 private static final long REFCNT_FIELD_OFFSET;
37 private static final AtomicIntegerFieldUpdater<AbstractReferenceCountedByteBuf> AIF_UPDATER;
38 private static final Object REFCNT_FIELD_VH;
39 private static final ReferenceCountUpdater<AbstractReferenceCountedByteBuf> updater;
40
41 static {
42 switch (ReferenceCountUpdater.updaterTypeOf(AbstractReferenceCountedByteBuf.class, "refCnt")) {
43 case Atomic:
44 AIF_UPDATER = newUpdater(AbstractReferenceCountedByteBuf.class, "refCnt");
45 REFCNT_FIELD_OFFSET = -1;
46 REFCNT_FIELD_VH = null;
47 updater = new AtomicReferenceCountUpdater<AbstractReferenceCountedByteBuf>() {
48 @Override
49 protected AtomicIntegerFieldUpdater<AbstractReferenceCountedByteBuf> updater() {
50 return AIF_UPDATER;
51 }
52 };
53 break;
54 case Unsafe:
55 AIF_UPDATER = null;
56 REFCNT_FIELD_OFFSET = getUnsafeOffset(AbstractReferenceCountedByteBuf.class, "refCnt");
57 REFCNT_FIELD_VH = null;
58 updater = new UnsafeReferenceCountUpdater<AbstractReferenceCountedByteBuf>() {
59 @Override
60 protected long refCntFieldOffset() {
61 return REFCNT_FIELD_OFFSET;
62 }
63 };
64 break;
65 case VarHandle:
66 AIF_UPDATER = null;
67 REFCNT_FIELD_OFFSET = -1;
68 REFCNT_FIELD_VH = PlatformDependent.findVarHandleOfIntField(MethodHandles.lookup(),
69 AbstractReferenceCountedByteBuf.class, "refCnt");
70 updater = new VarHandleReferenceCountUpdater<AbstractReferenceCountedByteBuf>() {
71 @Override
72 protected VarHandle varHandle() {
73 return (VarHandle) REFCNT_FIELD_VH;
74 }
75 };
76 break;
77 default:
78 throw new Error("Unknown updater type for AbstractReferenceCountedByteBuf");
79 }
80 }
81
82
83 @SuppressWarnings({"unused", "FieldMayBeFinal"})
84 private volatile int refCnt;
85
86 protected AbstractReferenceCountedByteBuf(int maxCapacity) {
87 super(maxCapacity);
88 updater.setInitialValue(this);
89 }
90
91 @Override
92 boolean isAccessible() {
93
94
95 return updater.isLiveNonVolatile(this);
96 }
97
98 @Override
99 public int refCnt() {
100 return updater.refCnt(this);
101 }
102
103
104
105
106 protected final void setRefCnt(int refCnt) {
107 updater.setRefCnt(this, refCnt);
108 }
109
110
111
112
113 protected final void resetRefCnt() {
114 updater.resetRefCnt(this);
115 }
116
117 @Override
118 public ByteBuf retain() {
119 return updater.retain(this);
120 }
121
122 @Override
123 public ByteBuf retain(int increment) {
124 return updater.retain(this, increment);
125 }
126
127 @Override
128 public ByteBuf touch() {
129 return this;
130 }
131
132 @Override
133 public ByteBuf touch(Object hint) {
134 return this;
135 }
136
137 @Override
138 public boolean release() {
139 return handleRelease(updater.release(this));
140 }
141
142 @Override
143 public boolean release(int decrement) {
144 return handleRelease(updater.release(this, decrement));
145 }
146
147 private boolean handleRelease(boolean result) {
148 if (result) {
149 deallocate();
150 }
151 return result;
152 }
153
154
155
156
157 protected abstract void deallocate();
158 }