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 }