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.ReferenceCountUpdater.UpdaterType;
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 AbstractReferenceCounted implements ReferenceCounted {
36 private static final long REFCNT_FIELD_OFFSET;
37 private static final AtomicIntegerFieldUpdater<AbstractReferenceCounted> AIF_UPDATER;
38 private static final Object REFCNT_FIELD_VH;
39 private static final ReferenceCountUpdater<AbstractReferenceCounted> updater;
40
41 static {
42 UpdaterType updaterType = ReferenceCountUpdater.updaterTypeOf(AbstractReferenceCounted.class, "refCnt");
43 switch (updaterType) {
44 case Atomic:
45 AIF_UPDATER = newUpdater(AbstractReferenceCounted.class, "refCnt");
46 REFCNT_FIELD_OFFSET = -1;
47 REFCNT_FIELD_VH = null;
48 updater = new AtomicReferenceCountUpdater<AbstractReferenceCounted>() {
49 @Override
50 protected AtomicIntegerFieldUpdater<AbstractReferenceCounted> updater() {
51 return AIF_UPDATER;
52 }
53 };
54 break;
55 case Unsafe:
56 AIF_UPDATER = null;
57 REFCNT_FIELD_OFFSET = getUnsafeOffset(AbstractReferenceCounted.class, "refCnt");
58 REFCNT_FIELD_VH = null;
59 updater = new UnsafeReferenceCountUpdater<AbstractReferenceCounted>() {
60 @Override
61 protected long refCntFieldOffset() {
62 return REFCNT_FIELD_OFFSET;
63 }
64 };
65 break;
66 case VarHandle:
67 AIF_UPDATER = null;
68 REFCNT_FIELD_OFFSET = -1;
69 REFCNT_FIELD_VH = PlatformDependent.findVarHandleOfIntField(MethodHandles.lookup(),
70 AbstractReferenceCounted.class, "refCnt");
71 updater = new VarHandleReferenceCountUpdater<AbstractReferenceCounted>() {
72 @Override
73 protected VarHandle varHandle() {
74 return (VarHandle) REFCNT_FIELD_VH;
75 }
76 };
77 break;
78 default:
79 throw new Error("Unexpected updater type for AbstractReferenceCounted: " + updaterType);
80 }
81 }
82
83
84 @SuppressWarnings({"unused", "FieldMayBeFinal"})
85 private volatile int refCnt = updater.initialValue();
86
87 @Override
88 public int refCnt() {
89 return updater.refCnt(this);
90 }
91
92
93
94
95 protected final void setRefCnt(int refCnt) {
96 updater.setRefCnt(this, refCnt);
97 }
98
99 @Override
100 public ReferenceCounted retain() {
101 return updater.retain(this);
102 }
103
104 @Override
105 public ReferenceCounted retain(int increment) {
106 return updater.retain(this, increment);
107 }
108
109 @Override
110 public ReferenceCounted touch() {
111 return touch(null);
112 }
113
114 @Override
115 public boolean release() {
116 return handleRelease(updater.release(this));
117 }
118
119 @Override
120 public boolean release(int decrement) {
121 return handleRelease(updater.release(this, decrement));
122 }
123
124 private boolean handleRelease(boolean result) {
125 if (result) {
126 deallocate();
127 }
128 return result;
129 }
130
131
132
133
134 protected abstract void deallocate();
135 }