1 /*
2  * Copyright 2013 The Netty Project
3  *
4  * The Netty Project licenses this file to you under the Apache License,
5  * version 2.0 (the "License"); you may not use this file except in compliance
6  * with the License. You may obtain a copy of the License at:
7  *
8  *   http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13  * License for the specific language governing permissions and limitations
14  * under the License.
15  */
16 
17 module hunt.net.buffer.AbstractReferenceCountedByteBuf;
18 
19 import hunt.net.buffer.AbstractByteBuf;
20 import hunt.net.buffer.ByteBuf;
21 import hunt.net.buffer.ByteBufUtil;
22 import hunt.net.buffer.ReferenceCountUpdater;
23 
24 
25 import hunt.io.ByteBuffer;
26 import hunt.Exceptions;
27 import hunt.net.Exceptions;
28 import hunt.stream.Common;
29 import hunt.util.StringBuilder;
30 
31 import std.conv;
32 import std.format;
33 import std.concurrency : initOnce;
34 
35 // import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
36 
37 // import io.netty.util.internal.ReferenceCountUpdater;
38 
39 /**
40  * Abstract base class for {@link ByteBuf} implementations that count references.
41  */
42 abstract class AbstractReferenceCountedByteBuf : AbstractByteBuf {
43 
44     alias IntegerFieldUpdater = AtomicIntegerFieldUpdater!(AbstractReferenceCountedByteBuf, "_refCnt");
45     alias RefCntUpdater = ReferenceCountUpdater!(AbstractReferenceCountedByteBuf, "_refCnt");
46 
47     private static IntegerFieldUpdater AIF_UPDATER() {
48         __gshared IntegerFieldUpdater inst;
49         return initOnce!inst(new IntegerFieldUpdater());
50     }
51 
52     private static RefCntUpdater updater() {
53         __gshared RefCntUpdater inst;
54         return initOnce!inst(new class RefCntUpdater {
55                 override
56                 protected IntegerFieldUpdater updater() {
57                     return AIF_UPDATER;
58             }
59         });
60 
61     }
62             
63 
64 
65     // Value might not equal "real" reference count, all access should be via the updater
66     private shared int _refCnt; // = updater.initialValue();
67 
68     protected this(int maxCapacity) {
69         super(maxCapacity);
70         _refCnt = updater.initialValue();
71     }
72 
73     override
74     bool isAccessible() {
75         // Try to do non-volatile read for performance as the ensureAccessible() is racy anyway and only provide
76         // a best-effort guard.
77         return updater.isLiveNonVolatile(this);
78     }
79 
80     // override
81     int refCnt() {
82         return updater.refCnt(this);
83     }
84 
85     /**
86      * An unsafe operation intended for use by a subclass that sets the reference count of the buffer directly
87      */
88     protected final void setRefCnt(int refCnt) {
89         updater.setRefCnt(this, refCnt);
90     }
91 
92     /**
93      * An unsafe operation intended for use by a subclass that resets the reference count of the buffer to 1
94      */
95     protected final void resetRefCnt() {
96         // updater.resetRefCnt(this);
97     }
98 
99     override
100     ByteBuf retain() {
101         // return updater.retain(this);
102         implementationMissing(false);
103         return this;
104     }
105 
106     override
107     ByteBuf retain(int increment) {
108         // return updater.retain(this, increment);
109 
110         return this;
111     }
112 
113     override
114     ByteBuf touch() {
115         return this;
116     }
117 
118     override
119     ByteBuf touch(Object hint) {
120         return this;
121     }
122 
123     // override
124     bool release() {
125         return handleRelease(updater.release(this));
126     }
127 
128     // override
129     bool release(int decrement) {
130         return handleRelease(updater.release(this, decrement));
131     }
132 
133     private bool handleRelease(bool result) {
134         if (result) {
135             deallocate();
136         }
137         return result;
138     }
139 
140     /**
141      * Called once {@link #refCnt()} is equals 0.
142      */
143     protected abstract void deallocate();
144 }