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