www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - How to instantiate class object NOT in the GC heap

reply Alexandr Druzhinin <drug2004 bk.ru> writes:
Hello,

I need something like that - 
http://digitalmars.com/techtips/class_objects.html, but more portable. I 
saw it sometime ago, but now can not find anything.
Could someone help me.
Jul 15 2012
parent reply =?UTF-8?B?QWxleCBSw7hubmUgUGV0ZXJzZW4=?= <alex lycus.org> writes:
On 15-07-2012 15:43, Alexandr Druzhinin wrote:
 Hello,

 I need something like that -
 http://digitalmars.com/techtips/class_objects.html, but more portable. I
 saw it sometime ago, but now can not find anything.
 Could someone help me.
This is how you do it in modern D: import core.stdc.stdlib, std.conv; class A {} void main() { // allocate and initialize auto size = __traits(classInstanceSize, A); auto mem = malloc(size)[0 .. size]; auto a = emplace!A(mem); // a is now an instance of A in the libc heap. // finalize and deallocate clear(a); free(mem.ptr); // or free(cast(void*)a); } clear() calls the finalizer on the object you give it. In the case of A, there is no finalizer, so it doesn't matter. It would matter if you had something like: class A { private void* resource; ~this() { freeResource(resource); } } -- Alex Rønne Petersen alex lycus.org http://lycus.org
Jul 15 2012
next sibling parent reply Alexandr Druzhinin <drug2004 bk.ru> writes:
15.07.2012 20:50, Alex Rønne Petersen пишет:
 This is how you do it in modern D:

 import core.stdc.stdlib, std.conv;

 class A {}

 void main()
 {
      // allocate and initialize
      auto size = __traits(classInstanceSize, A);
      auto mem = malloc(size)[0 .. size];
      auto a = emplace!A(mem);

      // a is now an instance of A in the libc heap.

      // finalize and deallocate
      clear(a);
      free(mem.ptr); // or free(cast(void*)a);
 }

 clear() calls the finalizer on the object you give it. In the case of A,
 there is no finalizer, so it doesn't matter. It would matter if you had
 something like:

 class A
 {
      private void* resource;

      ~this()
      {
          freeResource(resource);
      }
 }
how to pass arguments to ctor of class A?
Jul 15 2012
parent reply =?UTF-8?B?QWxleCBSw7hubmUgUGV0ZXJzZW4=?= <alex lycus.org> writes:
On 15-07-2012 16:46, Alexandr Druzhinin wrote:
 15.07.2012 20:50, Alex Rønne Petersen пишет:
 This is how you do it in modern D:

 import core.stdc.stdlib, std.conv;

 class A {}

 void main()
 {
      // allocate and initialize
      auto size = __traits(classInstanceSize, A);
      auto mem = malloc(size)[0 .. size];
      auto a = emplace!A(mem);

      // a is now an instance of A in the libc heap.

      // finalize and deallocate
      clear(a);
      free(mem.ptr); // or free(cast(void*)a);
 }

 clear() calls the finalizer on the object you give it. In the case of A,
 there is no finalizer, so it doesn't matter. It would matter if you had
 something like:

 class A
 {
      private void* resource;

      ~this()
      {
          freeResource(resource);
      }
 }
how to pass arguments to ctor of class A?
You pass those after the 'mem' argument to emplace. So, for example: auto a = emplace!A(mem, "foo", bar, 'b', 'a', 'z'); -- Alex Rønne Petersen alex lycus.org http://lycus.org
Jul 15 2012
parent Alexandr Druzhinin <drug2004 bk.ru> writes:
15.07.2012 22:03, Alex Rønne Petersen пишет:
 You pass those after the 'mem' argument to emplace. So, for example:

 auto a = emplace!A(mem, "foo", bar, 'b', 'a', 'z');
thanks for your help!
Jul 15 2012
prev sibling parent reply "bearophile" <bearophileHUGS lycos.com> writes:
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. Bye, bearophile
Jul 15 2012
next sibling parent =?UTF-8?B?QWxleCBSw7hubmUgUGV0ZXJzZW4=?= <alex lycus.org> writes:
On 15-07-2012 18:34, 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. Bye, bearophile
malloc is guaranteed to allocate on a machine word boundary which I think is sufficient. Bug-prone? Sure. But I don't think there's much we can do about that without language support... -- Alex Rønne Petersen alex lycus.org http://lycus.org
Jul 15 2012
prev sibling parent reply Jonathan M Davis <jmdavisProg gmx.com> writes:
On Sunday, July 15, 2012 18:34:44 bearophile wrote:
 Alex R=C3=B8nne 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= =20 probably become possible to do something like auto alloc =3D getMallocAllator(); auto obj =3D alloc.make!T(args1, args2, args3); - Jonathan M Davis
Jul 15 2012
parent reply Benjamin Thaut <code benjamin-thaut.de> writes:
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
Jul 15 2012
parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Sunday, July 15, 2012 21:14:40 Benjamin Thaut wrote:
 Am 15.07.2012 21:06, schrieb Jonathan M Davis:
 On Sunday, July 15, 2012 18:34:44 bearophile wrote:
 Alex R=C3=B8nne 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.
=20 It'll probably become easier to do once we have allocators, since i=
t'll
 probably become possible to do something like
=20
 auto alloc =3D getMallocAllator();
 auto obj =3D alloc.make!T(args1, args2, args3);
=20
 - Jonathan M Davis
=20 emplace has quite some issues especially when it can't find any constructor to call you have no clue whats happening. Here is my cust=
om
 new which does quite some special case handling:
Well, if you have suggestions on how to improve emplace, then please cr= eate an=20 enhancement request and/or a pull request. And with properly written cu= stom=20 allocators, all of the special casing should then be _in_ the allocator= where=20 you won't have to deal with it, making it so that you'd only really nee= d=20 emplace directly when you're doing something that none of the custom=20= allocators will do (or you're writing your own custom allocator). - Jonathan M Davis
Jul 15 2012