Jump to page: 1 2
Thread overview
D needs emplacement new
Apr 25, 2015
Namespace
Apr 25, 2015
Adam D. Ruppe
Apr 25, 2015
Namespace
Apr 25, 2015
Adam D. Ruppe
Apr 25, 2015
Namespace
Apr 25, 2015
weaselcat
Apr 25, 2015
weaselcat
Apr 25, 2015
Namespace
Apr 25, 2015
weaselcat
Apr 25, 2015
Namespace
Apr 26, 2015
Namespace
Apr 27, 2015
Namespace
Apr 27, 2015
anonymous
Apr 27, 2015
Adam D. Ruppe
May 01, 2015
anonymous
Apr 25, 2015
weaselcat
Apr 25, 2015
Adam D. Ruppe
April 25, 2015
Consider both of these scripts: test_gc_new.d (http://dpaste.dzfl.pl/4f36b165c502) and test_gc_emplace_new.d (http://dpaste.dzfl.pl/ff4e3c35479f)

and these results:

test_gc_new:

>test_gc_new.exe "--DRT-gcopt=profile:1"
        Number of collections:  140
        Total GC prep time:  0 milliseconds
        Total mark time:  5 milliseconds
        Total sweep time:  9 milliseconds
        Total page recovery time:  2 milliseconds
        Max Pause Time:  0 milliseconds
        Grand total GC time:  18 milliseconds
GC summary:    5 MB,  140 GC   18 ms, Pauses    6 ms <    0 ms


test_gc_emplace_new:

>test_gc_emplace_new.exe "--DRT-gcopt=profile:1"
        Number of collections:  2
        Total GC prep time:  0 milliseconds
        Total mark time:  0 milliseconds
        Total sweep time:  0 milliseconds
        Total page recovery time:  0 milliseconds
        Max Pause Time:  0 milliseconds
        Grand total GC time:  0 milliseconds
GC summary:    5 MB,    2 GC    0 ms, Pauses    0 ms <    0 ms

As you can see, thanks to the emplacement, I have 138 less GC collections. In C++ you can do

new (f) Foo(...) instead of my New!(Foo)(f, ...)

The C++ version is a lot more readable, nicer and safer. Therefore D should (since it says it is a system language like C++) add an equal syntax or, at least, implement a library version like mine to allow people a nice and easy way to reuse their object. We already have emplace (which my implementation uses) but to write emplace((cast(void*) obj)[0 .. __traits(classInstanceSize, Foo)], ...) is not nice, not intuitive and not safe and can be improved.
April 25, 2015
You could just call the constructor again to reuse an object. I guess you should also reinitialize the memory, but that's pretty easy too.

Instead of placement new to reuse an object, make a function like reset() or reinitialize() that destructs the first, then copies the init back over and calls the constructor again.



Something like this:

void reinitialize(ClassName, CtorArgs...)(ClassName obj, CtorArgs args) {
    assert(typeid(obj) == typeid(ClassName),
        "Don't use this on interfaces or base classes!");
    static if(__traits(hasMember, obj, "__dtor"))
        obj.__dtor();
    (cast(void*) obj)[0 .. typeid(obj).init.length] = typeid(obj).init[];
    static if(__traits(hasMember, obj, "__ctor"))
        obj.__ctor(args);
}


Then, you create it however up front and just reinitialize it when you're all set. I think that is a bit clearer in meaning than placement new as well.
April 25, 2015
On Saturday, 25 April 2015 at 18:46:52 UTC, Adam D. Ruppe wrote:
> You could just call the constructor again to reuse an object. I guess you should also reinitialize the memory, but that's pretty easy too.
>
> Instead of placement new to reuse an object, make a function like reset() or reinitialize() that destructs the first, then copies the init back over and calls the constructor again.
>
>
>
> Something like this:
>
> void reinitialize(ClassName, CtorArgs...)(ClassName obj, CtorArgs args) {
>     assert(typeid(obj) == typeid(ClassName),
>         "Don't use this on interfaces or base classes!");
>     static if(__traits(hasMember, obj, "__dtor"))
>         obj.__dtor();
>     (cast(void*) obj)[0 .. typeid(obj).init.length] = typeid(obj).init[];
>     static if(__traits(hasMember, obj, "__ctor"))
>         obj.__ctor(args);
> }
>
>
> Then, you create it however up front and just reinitialize it when you're all set. I think that is a bit clearer in meaning than placement new as well.

Nice name, fits better. But that should be in phobos, don't you think?
April 25, 2015
On Saturday, 25 April 2015 at 18:50:59 UTC, Namespace wrote:
> Nice name, fits better. But that should be in phobos, don't you think?

meh, it might be nice to have, but not being in phobos isn't a big deal to me for little utilities like this.
April 25, 2015
On Saturday, 25 April 2015 at 18:46:52 UTC, Adam D. Ruppe wrote:
> You could just call the constructor again to reuse an object. I guess you should also reinitialize the memory, but that's pretty easy too.
>
> Instead of placement new to reuse an object, make a function like reset() or reinitialize() that destructs the first, then copies the init back over and calls the constructor again.
>
>
>
> Something like this:
>
> void reinitialize(ClassName, CtorArgs...)(ClassName obj, CtorArgs args) {
>     assert(typeid(obj) == typeid(ClassName),
>         "Don't use this on interfaces or base classes!");
>     static if(__traits(hasMember, obj, "__dtor"))
>         obj.__dtor();
>     (cast(void*) obj)[0 .. typeid(obj).init.length] = typeid(obj).init[];
>     static if(__traits(hasMember, obj, "__ctor"))
>         obj.__ctor(args);
> }
>
>
> Then, you create it however up front and just reinitialize it when you're all set. I think that is a bit clearer in meaning than placement new as well.

doesn't this have the issue of not calling the ctor/dtor of nested objects?
April 25, 2015
On Saturday, 25 April 2015 at 18:57:13 UTC, Adam D. Ruppe wrote:
> On Saturday, 25 April 2015 at 18:50:59 UTC, Namespace wrote:
>> Nice name, fits better. But that should be in phobos, don't you think?
>
> meh, it might be nice to have, but not being in phobos isn't a big deal to me for little utilities like this
I'm sure newcomers (especially those coming from C++) would be delighted if they had the possibility to reuse their memory. In addition, it could be impossible for them to write such "hack" itself.
I already hear the cries: "D wasted memory" and: "I can not reuse my memory".
And then it would be less attractive for such people, to switch to D.

I would suggest something like:
----
T emplace(T, U...)(ref T obj, auto ref U args) if (is(T == class)) {
    if (!obj)
        return null;

    import std.conv : emplace; // temporary, as long it is not in std.conv

    enum ClassSizeOf = __traits(classInstanceSize, T);

    void[] buf = (cast(void*) obj)[0 .. ClassSizeOf];
    return emplace!(T)(buf, args);
}

T emplaceOrNew(T, U...)(ref T obj, auto ref U args) if (is(T == class)) {
    if (!obj)
        return new T(args);
    return emplace(obj, args);
}
----
April 25, 2015
On Saturday, 25 April 2015 at 19:09:15 UTC, Namespace wrote:
> On Saturday, 25 April 2015 at 18:57:13 UTC, Adam D. Ruppe wrote:
>> On Saturday, 25 April 2015 at 18:50:59 UTC, Namespace wrote:
>>> Nice name, fits better. But that should be in phobos, don't you think?
>>
>> meh, it might be nice to have, but not being in phobos isn't a big deal to me for little utilities like this
> I'm sure newcomers (especially those coming from C++) would be delighted if they had the possibility to reuse their memory. In addition, it could be impossible for them to write such "hack" itself.
> I already hear the cries: "D wasted memory" and: "I can not reuse my memory".
> And then it would be less attractive for such people, to switch to D.
>
> I would suggest something like:
> ----
> T emplace(T, U...)(ref T obj, auto ref U args) if (is(T == class)) {
>     if (!obj)
>         return null;
>
>     import std.conv : emplace; // temporary, as long it is not in std.conv
>
>     enum ClassSizeOf = __traits(classInstanceSize, T);
>
>     void[] buf = (cast(void*) obj)[0 .. ClassSizeOf];
>     return emplace!(T)(buf, args);
> }
>
> T emplaceOrNew(T, U...)(ref T obj, auto ref U args) if (is(T == class)) {
>     if (!obj)
>         return new T(args);
>     return emplace(obj, args);
> }
> ----

hmm...
http://dlang.org/phobos/std_conv.html#.emplace
April 25, 2015
On Saturday, 25 April 2015 at 19:14:41 UTC, weaselcat wrote:
> On Saturday, 25 April 2015 at 19:09:15 UTC, Namespace wrote:
>> On Saturday, 25 April 2015 at 18:57:13 UTC, Adam D. Ruppe wrote:
>>> On Saturday, 25 April 2015 at 18:50:59 UTC, Namespace wrote:
>>>> Nice name, fits better. But that should be in phobos, don't you think?
>>>
>>> meh, it might be nice to have, but not being in phobos isn't a big deal to me for little utilities like this
>> I'm sure newcomers (especially those coming from C++) would be delighted if they had the possibility to reuse their memory. In addition, it could be impossible for them to write such "hack" itself.
>> I already hear the cries: "D wasted memory" and: "I can not reuse my memory".
>> And then it would be less attractive for such people, to switch to D.
>>
>> I would suggest something like:
>> ----
>> T emplace(T, U...)(ref T obj, auto ref U args) if (is(T == class)) {
>>    if (!obj)
>>        return null;
>>
>>    import std.conv : emplace; // temporary, as long it is not in std.conv
>>
>>    enum ClassSizeOf = __traits(classInstanceSize, T);
>>
>>    void[] buf = (cast(void*) obj)[0 .. ClassSizeOf];
>>    return emplace!(T)(buf, args);
>> }
>>
>> T emplaceOrNew(T, U...)(ref T obj, auto ref U args) if (is(T == class)) {
>>    if (!obj)
>>        return new T(args);
>>    return emplace(obj, args);
>> }
>> ----
>
> hmm...
> http://dlang.org/phobos/std_conv.html#.emplace

woops, accidentally posted before finishing

I was going to say that this should probably just be an overload of emplace if it isn't already, seems odd if it isn't.
April 25, 2015
> hmm...
> http://dlang.org/phobos/std_conv.html#.emplace

> constructs an object of non-class type T at that address.

Non-Class. ;)
April 25, 2015
On Saturday, 25 April 2015 at 19:16:21 UTC, Namespace wrote:
>> hmm...
>> http://dlang.org/phobos/std_conv.html#.emplace
>
>> constructs an object of non-class type T at that address.
>
> Non-Class. ;)

There's a class overload 3 down
T emplace(T, Args...)(void[] chunk, auto ref Args args) if (is(T == class));
« First   ‹ Prev
1 2