How to instantiate class object NOT in the GC heap

Benjamin Thaut code at benjamin-thaut.de
Sun Jul 15 12:14:40 PDT 2012


Am 15.07.2012 21:06, schrieb Jonathan M Davis:
> On Sunday, July 15, 2012 18:34:44 bearophile wrote:
>> Alex Rønne Petersen:
>>> This is how you do it in modern D:
>> This seems fiddly and bug-prone (and eventually fit to go in the
>> D FAQ).
>> Maybe it needs to use an aligned_malloc, to avoid aligning
>> troubles in the class.
>
> It'll probably become easier to do once we have allocators, since it'll
> probably become possible to do something like
>
> auto alloc = getMallocAllator();
> auto obj = alloc.make!T(args1, args2, args3);
>
> - Jonathan M Davis
>

emplace has quite some issues especially when it can't find any 
constructor to call you have no clue whats happening. Here is my custom 
new which does quite some special case handling:

auto New(T,ARGS...)(ARGS args)
{
   return 
AllocatorNew!(T,StdAllocator,ARGS)(StdAllocator.globalInstance, args);
}

string ListAvailableCtors(T)()
{
   string result = "";
   foreach(t; __traits(getOverloads, T, "__ctor"))
     result ~= typeof(t).stringof ~ "\n";
   return result;
}

auto AllocatorNew(T,AT,ARGS...)(AT allocator, ARGS args)
{
   static if(is(T == class))
   {
     size_t memSize = __traits(classInstanceSize,T);
     static assert(!__traits(compiles, { T temp; bool test = temp.outer 
!is null; }), "inner classes are not implemented yet");
   }
   else {
     size_t memSize = T.sizeof;
   }

   void[] mem = allocator.AllocateMemory(memSize);
   debug {
     assert(mem.ptr !is null,"Out of memory");
     auto address = cast(size_t)mem.ptr;
     auto alignment = T.alignof;
     assert(address % alignment == 0,"Missaligned memory");
   }

   //initialize
   static if(is(T == class))
   {
     auto ti = typeid(StripModifier!T);
     assert(memSize == ti.init.length,"classInstanceSize and 
typeid(T).init.length do not match");
     mem[] = (cast(void[])ti.init)[];
     auto result = (cast(T)mem.ptr);
     static if(is(typeof(result.__ctor(args))))
     {
       scope(failure)
       {
         AllocatorDelete(allocator, result);
       }
       result.__ctor(args);
     }
     else
     {
       static assert(args.length == 0 && !is(typeof(&T.__ctor)),
                 "Don't know how to initialize an object of type "
                 ~ T.stringof ~ " with arguments:\n" ~ ARGS.stringof ~ 
"\nAvailable ctors:\n" ~ ListAvailableCtors!T() );
     }

     static if(is(AT == StdAllocator))
     {
       allocator.SetIsClass(mem.ptr);
     }

     static if(is(T : RefCounted))
     {
       result.SetAllocator(allocator);
       return ReturnRefCounted!T(result);
     }
     else
     {
       return result;
     }
   }
   else
   {
     *(cast(T*)mem) = T.init;
     auto result = (cast(T*)mem);
     static if(ARGS.length > 0 && is(typeof(result.__ctor(args))))
     {
       result.__ctor(args);
     }
     else static if(ARGS.length > 0)
     {
       static assert(args.length == 0 && !is(typeof(&T.__ctor)),
                 "Don't know how to initialize an object of type "
                 ~ T.stringof ~ " with arguments " ~ args.stringof ~ 
"\nAvailable ctors:\n" ~ ListAvailableCtors!T() );
     }
     return result;
   }
}

Kind Regards
Benjamin Thaut



More information about the Digitalmars-d-learn mailing list