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