digitalmars.D.learn - Reuse object memory?
- Namespace (38/38) Apr 19 2015 Is it somehow possible to reuse the memory of an object?
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (29/33) Apr 19 2015 Yes, when you cast a class variable to void*, you get the address of the...
- Namespace (13/13) Apr 19 2015 And if I have an already instantiated object?
- Namespace (19/19) Apr 19 2015 It seems that D has currently no direct support to reuse object
- Namespace (14/48) Apr 20 2015 I'm sorry if I annoy you, but I would really like to know how you
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (29/43) Apr 20 2015 Something like the following works. I chose to set the old object to
- Namespace (4/4) Apr 20 2015 Thank you. Do you mean this is worth a PR, to add this
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (11/13) Apr 20 2015 I am not familiar with such a need so I don't have a strong opinion.
- Namespace (11/26) Apr 20 2015 I have currently an array of objects which may be reloaded (it's
- "Marc =?UTF-8?B?U2Now7x0eiI=?= <schuetzm gmx.net> (3/29) Apr 21 2015 It's probably better to call the destructor here before calling
Is it somehow possible to reuse the memory of an object? My current idea is: ---- nogc T emplace(T, Args...)(ref T obj, auto ref Args args) nothrow if (is(T == class)) { if (obj is null) return null; enum size_t SIZE = __traits(classInstanceSize, T); void[] buf = (cast(void*) obj)[0 .. SIZE]; buf = typeid(T).init[]; //obj = cast(T) buf.ptr; static if (args.length) obj.__ctor(args); return obj; } Foo f = new Foo(42); Foo f2 = emplace(f, 23); ---- But is there a more elegant way to do that? Maybe without calling the internal __ctor? In C++ you can do that: ---- #include <iostream> class Foo { public: int id; explicit Foo(int _id) : id(_id) { } }; int main() { Foo* f = new Foo(42); std::cout << f << ':' << f->id << std::endl; new (f) Foo(23); std::cout << f << ':' << f->id << std::endl; delete f; } ----
Apr 19 2015
On 04/19/2015 09:04 AM, Namespace wrote:Is it somehow possible to reuse the memory of an object?Yes, when you cast a class variable to void*, you get the address of the object.nogc T emplace(T, Args...)(ref T obj, auto ref Args args) nothrow if (is(T == class)) {There is already std.conv.emplace: import std.conv; import core.memory; class Foo { int i; this(int i) { this.i = i; } } void main() { void* buffer = GC.calloc(1234); enum FooSize = __traits(classInstanceSize, Foo); /* These two object are constructed on a void[] slice: */ auto f = emplace!Foo(buffer[0..FooSize], 42); auto f2 = emplace!Foo(buffer[0..FooSize], 43); /* f3 is constructed on top of an existing object: */ auto f2_addr = cast(void*)f2; auto f3 = emplace!Foo(f2_addr[0..FooSize], 44); /* At this point, all three reference the same object: */ assert(&f.i == &f2.i); assert(&f.i == &f3.i); } Ali
Apr 19 2015
And if I have an already instantiated object? ---- Foo f = new Foo(); // reuse f's memory ---- Is there an nicer way to override the memory instead of: ---- void[] buf = (cast(void*) f)[0 .. __traits(classInstanceSize, Foo)]; buf = typeid(Foo).init[]; // or: buf = f.classinfo.init[]; ---- ? The void* cast looks very ugly.
Apr 19 2015
It seems that D has currently no direct support to reuse object memory. D should add a new-placement syntax: ---- Foo f = new Foo(42); new (f) Foo(23); ---- and/or should add an emplace overload which takes an object: ---- T emplace(T, Args...)(ref T obj, auto ref Args args) if (is(T == class)) { if (obj is null) return null; enum size_t ClassSize = __traits(classInstanceSize, T); void[] buf = (cast(void*) obj)[0 .. ClassSize]; import std.conv : emplace; return emplace!(T)(buf, args); } ----
Apr 19 2015
On Sunday, 19 April 2015 at 21:17:18 UTC, Ali Çehreli wrote:On 04/19/2015 09:04 AM, Namespace wrote:I'm sorry if I annoy you, but I would really like to know how you would reuse already instantiated storage of an existing object. Example code: ---- final class Foo { uint id; nogc this(uint id) { this.id = id; } } Foo f = new Foo(42); ----Is it somehow possible to reuse the memory of an object?Yes, when you cast a class variable to void*, you get the address of the object.nogc T emplace(T, Args...)(ref T obj, auto ref Args args) nothrowif (is(T ==class)) {There is already std.conv.emplace: import std.conv; import core.memory; class Foo { int i; this(int i) { this.i = i; } } void main() { void* buffer = GC.calloc(1234); enum FooSize = __traits(classInstanceSize, Foo); /* These two object are constructed on a void[] slice: */ auto f = emplace!Foo(buffer[0..FooSize], 42); auto f2 = emplace!Foo(buffer[0..FooSize], 43); /* f3 is constructed on top of an existing object: */ auto f2_addr = cast(void*)f2; auto f3 = emplace!Foo(f2_addr[0..FooSize], 44); /* At this point, all three reference the same object: */ assert(&f.i == &f2.i); assert(&f.i == &f3.i); } Ali
Apr 20 2015
On 04/20/2015 12:05 PM, Namespace wrote:I'm sorry if I annoy youNot at all! :) Sorry for not responding earlier., but I would really like to know how you would reuse already instantiated storage of an existing object. Example code: ---- final class Foo { uint id; nogc this(uint id) { this.id = id; } } Foo f = new Foo(42); ----Something like the following works. I chose to set the old object to null but it is not necessary: final class Foo { uint id; nogc this(uint id) { this.id = id; } } C reuse(C, T...)(ref C old, T ctorParams) { import std.conv; import std.typetuple; enum objectSize = __traits(classInstanceSize, C); void* oldPlace = cast(void*)old; C newObject = emplace!C(oldPlace[0..objectSize], ctorParams); old = null; return newObject; } void main() { Foo f = new Foo(42); auto f2 = f.reuse(43); assert(f is null); assert(f2.id == 43); } Ali
Apr 20 2015
Thank you. Do you mean this is worth a PR, to add this functionality to Phobos? My current code looks like this: http://dpaste.dzfl.pl/19b78a600b6c
Apr 20 2015
On 04/20/2015 02:44 PM, Namespace wrote:Thank you. Do you mean this is worth a PR, to add this functionality to Phobos?I am not familiar with such a need so I don't have a strong opinion. However, if an object needs to be emplaced on top of an existing one, I can imagine that the original object was emplaced on some piece of memory anyway. In that case, the problem becomes "emplacing an object on a piece of memory", which is already supported by std.conv.emplace. Your idea seems to be for the case where the original object is created by some third party code, and that they want us to replace it with another object. If they are aware of the wholesale change in the object, fine. :) Ali
Apr 20 2015
On Monday, 20 April 2015 at 21:58:59 UTC, Ali Çehreli wrote:On 04/20/2015 02:44 PM, Namespace wrote:I have currently an array of objects which may be reloaded (it's a tilemap). If the array is reused, I can do that with: ---- arr.length = 0; arr.assumeSafeAppend(); ---- But then I thought: why not reuse the memory of the objects? In C++ you can do that very elegant, but in D I have to produce garbage since the old object stays alive until the GC collects it and I have to allocate new GC memory.Thank you. Do you mean this is worth a PR, to add this functionality to Phobos?I am not familiar with such a need so I don't have a strong opinion. However, if an object needs to be emplaced on top of an existing one, I can imagine that the original object was emplaced on some piece of memory anyway. In that case, the problem becomes "emplacing an object on a piece of memory", which is already supported by std.conv.emplace. Your idea seems to be for the case where the original object is created by some third party code, and that they want us to replace it with another object. If they are aware of the wholesale change in the object, fine. :) Ali
Apr 20 2015
On Monday, 20 April 2015 at 21:36:35 UTC, Ali Çehreli wrote:final class Foo { uint id; nogc this(uint id) { this.id = id; } } C reuse(C, T...)(ref C old, T ctorParams) { import std.conv; import std.typetuple; enum objectSize = __traits(classInstanceSize, C); void* oldPlace = cast(void*)old;It's probably better to call the destructor here before calling emplace, to complete the lifecycle of the old object.C newObject = emplace!C(oldPlace[0..objectSize], ctorParams); old = null; return newObject; } void main() { Foo f = new Foo(42); auto f2 = f.reuse(43); assert(f is null); assert(f2.id == 43); } Ali
Apr 21 2015