April 25, 2015
On Saturday, 25 April 2015 at 19:21:28 UTC, weaselcat wrote:
> 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));

Which accepts a void[] chunk:
----
Foo f = new Foo(...);
emplace!(Foo)((cast(void*) f)[0 .. __traits(classInstanceSize, Foo)], ...);
----
That doesn't look like a "simple and friendly" manner for me. And it is also still not intuitive, not nice and not safe.
April 25, 2015
 On Saturday, 25 April 2015 at 19:08:52 UTC, weaselcat wrote:
> doesn't this have the issue of not calling the ctor/dtor of nested objects?

You could also use .destroy(copy_of_obj); instead of __dtor which should handle that, I think.

Constructors are fine because there's no default construction in D anyway - the object's this() would be calling them anyway.
April 26, 2015
Since I'm unable to rebuild phobos on my Windows 8.1 PC, would someone else be interested, to apply a PR? The code (including comment) would be this:

----
/**
Given an existing object $(D obj), reinitialize the object of $(D class)
type $(D T) at that address. The constructor is passed the arguments
$(D Args), if any.

Returns: The reinitialized object
 */
T emplace(T, Args...)(ref T obj, auto ref Args args)
    if (is(T == class))
{
    enforce!ConvException(obj !is null, "emplace: Object is null and cannot be reinitialized");

    enum classSize = __traits(classInstanceSize, T);
    void[] buf = (cast(void*) obj)[0 .. classSize];
    return emplace!T(buf, args);
}
----

Unfortunately, I do not have much time to deal with the phobos-rebuilding problem, but I still want to improve phobos.
April 27, 2015
Since nobody wants to take that work, can at least someone explain me what is going on if I don't reinitialize the memorY?
I create 1000 Foo's 1000 times. After the first iteration there are 1000 unused Foo objects and the GC wants to reallocate another 1000 Foo's. Now, what happen? The GC sees that the previous 1000 objects are unused, remove them and allocate new and fresh memory for the current 1000 Foo's? Or does the GC see 1000 unused Foo's and reuse the memory? How can I observe if the later is true? If I store the pointer to the object to compare them, the GC will recognize that and will not finalize the object.
April 27, 2015
On Monday, 27 April 2015 at 11:47:46 UTC, Namespace wrote:
> I create 1000 Foo's 1000 times. After the first iteration there are 1000 unused Foo objects and the GC wants to reallocate another 1000 Foo's. Now, what happen? The GC sees that the previous 1000 objects are unused, remove them and allocate new and fresh memory for the current 1000 Foo's? Or does the GC see 1000 unused Foo's and reuse the memory?

Collected memory will be reused for new allocations. The GC won't necessarily reuse the exact memory of the 1000 old Foos for the 1000 new Foos, but chances are it actually will.

> How can I observe if the later is true? If I store the pointer to the object to compare them, the GC will recognize that and will not finalize the object.

You can store the pointer as a size_t on the GC heap, and the GC will not regard it as a pointer. Alternatively, you can store it on the C heap, which is also ignored by the GC.

Using size_t:

----
void main()
{
    import std.stdio;
    import core.memory: GC;

    auto pointerInDisguise = new size_t;
    *pointerInDisguise = cast(size_t) cast(void*) new Object;

    /* Not sure why stomping is necessary, but without this, the first
    try below fails. */
    static void stomp() {ubyte[1024] x;}
    stomp();

    GC.collect();
    writeln(cast(size_t) cast(void*) new Object == *pointerInDisguise);
        /* prints "true" => memory is reused */

    GC.collect();
    writeln(cast(size_t) cast(void*) new Object == *pointerInDisguise);
        /* prints "true" => memory is reused */
}
----
April 27, 2015
On Monday, 27 April 2015 at 13:12:51 UTC, anonymous wrote:
> You can store the pointer as a size_t on the GC heap, and the GC will not regard it as a pointer.

Doesn't the GC regard every 4/8 sequence of bytes as a pointer?
April 27, 2015
On Monday, 27 April 2015 at 13:29:03 UTC, Casper Færgemand wrote:
> Doesn't the GC regard every 4/8 sequence of bytes as a pointer?

Only on the stack. On the heap, it knows what type the data is and if it has a pointer or not.
May 01, 2015
On Monday, 27 April 2015 at 13:12:51 UTC, anonymous wrote:
> ----
> void main()
> {
>     import std.stdio;
>     import core.memory: GC;
>
>     auto pointerInDisguise = new size_t;
>     *pointerInDisguise = cast(size_t) cast(void*) new Object;
>
>     /* Not sure why stomping is necessary, but without this, the first
>     try below fails. */

Probably issue 9614 - Uninitialized holes in function stack frames confuses GC - https://issues.dlang.org/show_bug.cgi?id=9614

>     static void stomp() {ubyte[1024] x;}
>     stomp();
>     GC.collect();
>     writeln(cast(size_t) cast(void*) new Object == *pointerInDisguise);
>         /* prints "true" => memory is reused */
>
>     GC.collect();
>     writeln(cast(size_t) cast(void*) new Object == *pointerInDisguise);
>         /* prints "true" => memory is reused */
> }
> ----

1 2
Next ›   Last »