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