1 module rc.allocator; 2 3 import std.experimental.allocator; 4 import std.experimental.allocator.mallocator; 5 import std.experimental.allocator.building_blocks.affix_allocator; 6 7 static this() { RC.affixObj = allocatorObject(RC.affix); } 8 9 /// 10 struct RC 11 { 12 static: 13 /// 14 alias affix = AffixAllocator!(Mallocator,size_t,size_t).instance; 15 /// 16 IAllocator affixObj; 17 18 /// 19 auto make(T,A...)( auto ref A args ) 20 { return incRef( affixObj.make!T(args) ); } 21 22 /// 23 T[] makeArray(T,A...)( size_t length ) 24 { return incRef( affixObj.makeArray!T(length) ); } 25 26 /// 27 T[] makeArray(T,A...)( size_t length, auto ref T init ) 28 { return incRef( affixObj.makeArray!T(length,init) ); } 29 30 /// 31 private void dispose(T)( T* p ) { affixObj.dispose(p); } 32 33 /// 34 private void dispose(T)( T p ) 35 if( is(T == class) || is(T == interface) ) 36 { affixObj.dispose(p); } 37 38 /// 39 private void dispose(T)( T[] arr ) { affixObj.dispose(arr); } 40 41 /// 42 ref size_t refCount(T)( T p ) 43 if( is(T == class) || is(T == interface) ) 44 { return affix.prefix( (cast(void*)p)[0..__traits(classInstanceSize,T)] ); } 45 46 /// 47 ref size_t refCount(T)( T* p ) 48 { return affix.prefix( (cast(void*)p)[0..T.sizeof] ); } 49 50 /// 51 ref size_t refCount(T)( T[] arr ) 52 { return affix.prefix( cast(void[])arr ); } 53 54 /// 55 auto incRef(T)( auto ref T p ) 56 { 57 if( p is null ) return null; 58 refCount(p)++; 59 return p; 60 } 61 62 /// 63 auto decRef(T)( T p ) 64 { 65 if( p is null ) return null; 66 67 if( refCount(p) > 0 ) 68 { 69 refCount(p)--; 70 if( refCount(p) == 0 ) 71 { 72 dispose(p); 73 return null; 74 } 75 } 76 77 return p; 78 } 79 } 80 81 unittest 82 { 83 auto p = RC.make!int( 10 ); 84 assert( is( typeof(p) == int* ) ); 85 assert( *p == 10 ); 86 assert( RC.refCount(p) == 1 ); 87 p = RC.decRef(p); 88 assert( p is null ); 89 } 90 91 unittest 92 { 93 static int inc = 0; 94 95 static class A 96 { 97 this() { inc = 5; } 98 ~this() { inc = 2; } 99 } 100 101 assert( inc == 0 ); 102 auto a = RC.make!A(); 103 assert( RC.refCount(a) == 1 ); 104 auto b = a; 105 assert( RC.refCount(a) == 1 ); 106 RC.incRef(b); 107 assert( RC.refCount(a) == 2 ); 108 assert( RC.refCount(b) == 2 ); 109 assert( inc == 5 ); 110 a = RC.decRef(a); 111 assert( inc == 5 ); 112 assert( a !is null ); 113 a = RC.decRef(a); 114 assert( inc == 2 ); 115 assert( a is null ); 116 }