voile.refcnt
参照カウンタ
- alias
Allocator
= CountedInstance* delegate() pure nothrow; - アロケータCountedDataを作成する際、メモリを割り当てる関数の型。
- alias
Deallocator
= void delegate(CountedInstance* instance) pure nothrow @nogc; - デアロケータCountedDataを解放する際、メモリを解放する関数の型。
- template
isAllocator
(T...) if (T.length > 0 && isCallable!(T[0])) - アロケータかどうかを判定するExamples:
static assert(isAllocator!(CountedInstance* delegate() @safe pure nothrow)); static assert(isAllocator!(CountedInstance* delegate() @system pure nothrow const)); static assert(isAllocator!(CountedInstance* delegate() @system pure nothrow @nogc)); static assert(!isAllocator!(CountedInstance* delegate() @system nothrow @nogc)); static assert(!isAllocator!(CountedInstance* delegate() @system pure @nogc)); void aaa(); static assert(!isAllocator!aaa); CountedInstance* bbb() pure nothrow; static assert(isAllocator!bbb);
- template
isDeallocator
(T...) if (T.length > 0 && isCallable!(T[0])) - デアロケータかどうかを判定するExamples:
static assert(isDeallocator!(void delegate(CountedInstance*) @safe pure nothrow @nogc)); static assert(isDeallocator!(void delegate(CountedInstance*) @system pure nothrow @nogc)); static assert(isDeallocator!(void delegate(CountedInstance*) @system pure nothrow @nogc inout)); static assert(!isDeallocator!(void delegate(CountedInstance*) @system nothrow @nogc const)); static assert(!isDeallocator!(void delegate(CountedInstance*) @system pure @nogc)); void aaa(); static assert(!isDeallocator!aaa); void bbb(CountedInstance*) pure nothrow @nogc; static assert(isDeallocator!bbb);
- pure nothrow @nogc @safe auto
defaultAllocatorByMalloc
(size_t bufSize = 0); - malloc/freeによるアロケータ
- pure nothrow auto
defaultAllocatorByGC
(size_t bufSize = 0); - GCによるアロケータ
- struct
CountedInstance
; - 参照カウンタ用のデータを作成する
- int
counter
; - 参照カウンタ
- ubyte[]
rawData
; - 生データ(データのインスタンスと拡張領域を含むメモリ領域全体)
- Deallocator
deallocator
; - 解放時に呼び出すためのコールバック
- template
CountedImpl
(T) - 参照カウンタ用のデータを作成するmixinテンプレート
- inout pure nothrow @nogc @property @safe inout(ubyte)[]
buffer
(); - 生データ(データのインスタンスと拡張領域を含むメモリ領域全体)
- inout pure nothrow @nogc @property ref @trusted inout(T)
data
(); - データのインスタンス
- inout pure nothrow @nogc @property @safe inout(ubyte)[]
extra
(); - 拡張データ領域
- pure @nogc @system void
initializeCountedInstance
(ubyte[] refbuf);
pure @nogc @system voidinitializeCountedInstance
(size_t bufSize = T.sizeof);
voidinitializeCountedInstance
(Alloc)(scope Alloc alloc); - 初期化するNote: 本関数を呼び出して初期化した場合、正しくrelease(CountedInstanceのdeallocatorの呼び出し)をしなければ メモリリークする
- const pure nothrow @nogc @safe bool
opCast
(T)()
if(is(T == bool)); - キャスト
- pure @nogc @system int
addRef
(); - 参照カウンタ加算
- pure @system int
release
(); - 参照カウンタ減算と解放
- struct
CountedData
(T); - 参照カウントを持つを形成する(RefCounted専用)CountedImplを実装しており、isCountedData!Tでtrueを返す型です。 ただし、メソッドはすべてモジュール内ローカルとなっており、アクセスは許されません。 かならずRefCountedを通してアクセスしてください。
- template
isCountedData
(T) - RefCountedにできるデータか検証するRefCountedに直接対応可能な型は以下の特徴を備えています。
- 参照型か、ポインタのサイズと同じサイズ
- releaseまたはRelease関数を備えていて、それらは整数を返す
- addRefまたはAddRef関数を備えていて、それらは整数を返す
Parameters:T 調べたい型 See Also: CountedDataExamples:static struct S1 {} static assert(!isCountedData!S1); static assert(isCountedData!(CountedData!S1)); static struct S2 { size_t x; uint release() {return 0;} uint addRef(){return 0;} } static assert(isCountedData!S2); static assert(isCountedData!(CountedData!S2)); class C1 {} static assert(!isCountedData!C1); class C2 { uint release(){return 0;} uint addRef(){return 0;}} static assert( isCountedData!C2); static assert(!isCountedData!int); static assert(!isCountedData!(int*)); static assert(isCountedData!(CountedData!int));
- struct
RefCounted
(T); - 参照カウンタのあるデータを管理するisCountedDataなデータの参照カウントをコピーの発生や寿命の終了で自動的に増減させる。Parameters:
T isCountedDataなclass/interface/structのポインタ/size_tと同サイズのstruct、およびCountedDataのインスタンス See Also: isCountedDataExamples:string[] msg; static class C { int cnt; string[]* msg; this(int x, string[]* m) {cnt = x; msg = m; } ~this() @trusted {*msg ~= "dtor"; } int release() @trusted { cnt--; return cnt; } int addRef(){ cnt++; return cnt;} } { // コンストラクタを使うとカウント値が増える RefCounted!C dat1 = new C(0, (() @trusted => &msg)()); assert(dat1.cnt == 1); } // スコープを抜けてRefCountedのインスタンスの寿命が終わると、デストラクタが呼ばれる assert(msg == ["dtor"]);
- @trusted this(U)(U newRefData)
if(is(U : RefType!T)); - 参照カウンタを保持してアタッチ&加算する
- void
opAssign
(U)(U newRefData)
if(is(U : RefType!T)); - 参照カウンタを保持してアタッチ&加算する
- ref auto
opUnary
(string op)()
if(op == "*"); - 参照外し
- enum auto
isRefCounted
(T); - 参照カウンタかどうか確認しますExamples:
static assert(isRefCounted!(RefCounted!int)); static assert(!isRefCounted!(int*));
- template
RefCountedTypeOf
(T) if (isRefCounted!T) - 参照カウンタの元データの型を得ますExamples:
static assert(is(RefCountedTypeOf!(RefCounted!int) == int));
- bool
isInitialized
(T)(const ref RefCounted!T dat);
boolisEmpty
(T)(const ref RefCounted!T dat);
aliasisNull
= isEmpty(T)(const ref RefCounted!T dat); - 参照が初期化されているか確認するExamples:
RefCounted!int x; assert(!x.isInitialized()); assert(x.isEmpty()); assert(x.isNull()); x = createRefCounted!int(1); assert(x.isInitialized()); assert(!x.isEmpty()); assert(!x.isNull());
- pure nothrow @property void
attach
(T, U)(ref RefCounted!T rc, auto ref U newRefData)
if(is(U : RefType!T)); - 参照カウンタ加算せずにアタッチするExamples:
static class C { int cnt; this(int x) {cnt = x;} int release() @trusted { cnt--; return cnt; } int addRef(){ cnt++; return cnt;} } // コンストラクタを使うとカウント値が増える RefCounted!C dat1 = new C(1); assert(dat1.cnt == 2); dat1.release(); // attachを使うとカウント値が増えない RefCounted!C dat2; dat2.attach(new C(1)); assert(dat2.cnt == 1);
- pure nothrow ref inout(T)
deref
(T)(inout ref RefCounted!T rc); - 参照外しExamples:
auto x = createRefCounted!int(1); static assert (is(typeof(x.deref) == int)); x.deref = 2; assert(x == 2);
- pure nothrow inout(T)*
ptr
(T)(inout ref RefCounted!T rc); - ポインタを得るExamples:
auto x = createRefCounted!int(1); static assert (is(typeof(x.ptr) == int*)); *x = 2; assert(x == 2); (() @trusted => *(x.ptr) = 3)(); assert(x == 3);
- @trusted RefCounted!T
createRefCounted
(T, Args...)(auto ref Args args)
if(isRefCounted!T);
@trusted RefCounted!TcreateRefCounted
(T, Args...)(auto ref Args args)
if(is(T == class) && isCountedData!T);
@trusted RefCounted!TcreateRefCounted
(T, Args...)(auto ref Args args)
if(!isPointer!T && (is(T == struct) || is(T == union)) && isCountedData!T);
@trusted RefCounted!TcreateRefCounted
(T, Args...)(auto ref Args args)
if(isPointer!T && (is(PointerTarget!T == struct) || is(PointerTarget!T == union)) && isCountedData!T);
@trusted RefCounted!TcreateRefCounted
(T, Args...)(auto ref Args args)
if(!isCountedData!T);
@trusted RefCounted!TcreateRefCounted
(T, alias allocator, Args...)(auto ref Args args)
if(!isCountedData!T && isAllocator!allocator); - 参照カウンタを生成Examples:
enum short initCnt = 1; // class static class C { short cnt; this(int x) {cnt = 1;} int release(){ cnt--; return cnt; } int addRef(){ cnt++; return cnt;} } auto c = createRefCounted!C(1); auto c2 = c; assert(c.cnt == 2); // struct static struct S { short cnt; int release(){ cnt--; return cnt; } int addRef(){ cnt++; return cnt;} } // struct - for pointer auto s1 = createRefCounted!(S*)(initCnt); assert(s1.cnt == 1); static assert(isCountedData!(S*)); // struct - for CountedData auto s2 = createRefCounted!S(initCnt); auto s3 = s1; assert(s1.cnt == 2); auto s4 = s2; // s2, s4はCountedDataなので、インスタンスの中身ではなく // CountedDataのcounterが増加する assert(s2.cnt == 1); assert(s2.counter == 2); // for union static union U { short cnt; int release(){ cnt--; return cnt; } int addRef(){ cnt++; return cnt;} } auto u1 = createRefCounted!(U*)(initCnt); assert(u1.cnt == 1); static assert(isCountedData!(U*)); auto u2 = createRefCounted!U(initCnt); assert(u2.cnt == 1); auto u3 = u1; assert(u1.cnt == 2); auto u4 = u2; // u2, u4はCountedDataなので、インスタンスの中身ではなく // CountedDataのcounterが増加する assert(u2.cnt == 1); assert(u2.counter == 2); // for scalar data auto int1 = createRefCounted!int(1); // with allocator auto long1 = createRefCounted!(long, defaultAllocatorByGC(long.sizeof))(1);
- RefCounted!T
attachRefCounted
(T)(T newRefData)
if(isCountedData!T);
RefCounted!TattachRefCounted
(T)(RefType!T newRefData)
if(!isCountedData!T); - 参照カウンタを追加せずにRefCountedを得る
- pure nothrow @nogc @property @system inout(ubyte)[]
buffer
(T)(inout ref RefCounted!T rc)
if(!isCountedData!T || isInstanceOf!(CountedData, T)); - バッファ領域へアクセスバッファ領域は、Tのインスタンスと拡張領域のメモリ領域全体を指す。Note: release後に触れた場合、ダングリングポインタへのアクセスの可能性がある。 また、書き換えた場合、本来RefCountedで管理しているデータが損失する可能性がある。Examples:
auto dat = createRefCounted!int(1); assert(dat.buffer.length == 4); assert(dat == *cast(int*)dat.buffer.ptr);
- pure nothrow @nogc @property @system inout(ubyte)[]
extraBuffer
(T)(inout ref RefCounted!T rc)
if(!isCountedData!T || isInstanceOf!(CountedData, T)); - 拡張データ領域へアクセス初期化時にTのインスタンスより大きなバッファを与えることで、拡張データ領域を持つことができる。 この関数は拡張データ領域へのアクセス手段を提供する。Note: release後に触れた場合、ダングリングポインタへのアクセスの可能性がある。 また、書き換えた場合、本来RefCountedで管理しているデータが損失する可能性がある。Examples:
auto dat = createRefCounted!(int, defaultAllocatorByMalloc(int.sizeof + 4))(1); assert(dat.buffer.length == 8); assert(dat.extraBuffer.length == 4);
- pure nothrow @nogc @property @safe int
counter
(T)(const ref RefCounted!T rc)
if(!isCountedData!T || isInstanceOf!(CountedData, T)); - カウント値を得るExamples:
auto dat1 = createRefCounted!int(1); assert(dat1.counter == 1); { auto dat2 = dat1; assert(dat1.counter == 2); } assert(dat1.counter == 1);