1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package io.netty.util;
17
18 import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
19
20 import static io.netty.util.internal.ObjectUtil.checkPositive;
21
22
23
24
25 public abstract class AbstractReferenceCounted implements ReferenceCounted {
26
27 private static final AtomicIntegerFieldUpdater<AbstractReferenceCounted> refCntUpdater =
28 AtomicIntegerFieldUpdater.newUpdater(AbstractReferenceCounted.class, "refCnt");
29
30 private volatile int refCnt = 1;
31
32 @Override
33 public final int refCnt() {
34 return refCnt;
35 }
36
37
38
39
40 protected final void setRefCnt(int refCnt) {
41 refCntUpdater.set(this, refCnt);
42 }
43
44 @Override
45 public ReferenceCounted retain() {
46 return retain0(1);
47 }
48
49 @Override
50 public ReferenceCounted retain(int increment) {
51 return retain0(checkPositive(increment, "increment"));
52 }
53
54 private ReferenceCounted retain0(int increment) {
55 int oldRef = refCntUpdater.getAndAdd(this, increment);
56 if (oldRef <= 0 || oldRef + increment < oldRef) {
57
58 refCntUpdater.getAndAdd(this, -increment);
59 throw new IllegalReferenceCountException(oldRef, increment);
60 }
61 return this;
62 }
63
64 @Override
65 public boolean release() {
66 return release0(1);
67 }
68
69 @Override
70 public boolean release(int decrement) {
71 return release0(checkPositive(decrement, "decrement"));
72 }
73
74 private boolean release0(int decrement) {
75 int oldRef = refCntUpdater.getAndAdd(this, -decrement);
76 if (oldRef == decrement) {
77 deallocate();
78 return true;
79 } else if (oldRef < decrement || oldRef - decrement > oldRef) {
80
81 refCntUpdater.getAndAdd(this, decrement);
82 throw new IllegalReferenceCountException(oldRef, decrement);
83 }
84 return false;
85 }
86
87
88
89
90 protected abstract void deallocate();
91 }