On Wed, 26 Jan 2011 12:26:22 -0500, Andrei Alexandrescu <[email protected]> wrote:

On 1/26/11 10:17 AM, Steven Schveighoffer wrote:
On Wed, 26 Jan 2011 11:09:45 -0500, Andrej Mitrovic
<[email protected]> wrote:

I think I glanced over a recent svn commit that fixed this, though I'm
not sure.

No, it hasn't been fixed.

The fix is *really* simple, just have clear call rt_finalize (as Sean
pointed out on the mailing list)

-Steve

Steve, if you could point out what I need to do I'll be glad to do it right now. Better yet, feel free to try your hand at a git commit. It's fun!

*sweats nervously* I don't know, I'd like to read about how git works before doing a commit. I don't really understand it at all, I had the same problem with subversion when I started using it.

The fix is really easy, just change clear to this:

void clear(T)(T obj) if (is(T == class))
{
  rt_finalize(cast(void*)obj);
}

Here is the body of the current clear:

    if (!obj) return;
    auto ci = obj.classinfo;
    auto defaultCtor =
        cast(void function(Object)) ci.defaultConstructor;
    version(none) // enforce isn't available in druntime
        _enforce(defaultCtor || (ci.flags & 8) == 0);
    immutable size = ci.init.length;

    auto ci2 = ci;
    do
    {
        auto dtor = cast(void function(Object))ci2.destructor;
        if (dtor)
            dtor(obj);
        ci2 = ci2.base;
    } while (ci2)

    auto buf = (cast(void*) obj)[0 .. size];
    buf[] = ci.init;
    if (defaultCtor)
        defaultCtor(obj);

And the body of rt_finalize

    if (p) // not necessary if called from gc
    {
        ClassInfo** pc = cast(ClassInfo**)p;

        if (*pc)
        {
            ClassInfo c = **pc;
            byte[] w = c.init;

            try
            {
if (det || collectHandler is null || collectHandler(cast(Object)p))
                {
                    do
                    {
                        if (c.destructor)
                        {
                            fp_t fp = cast(fp_t)c.destructor;
                            (*fp)(cast(Object)p); // call destructor
                        }
                        c = c.base;
                    } while (c);
                }
                if ((cast(void**)p)[1]) // if monitor is not null
                    _d_monitordelete(cast(Object)p, det);
                (cast(byte*) p)[0 .. w.length] = w[];
            }
            catch (Throwable e)
            {
                onFinalizeError(**pc, e);
            }
            finally
            {
                *pc = null; // zero vptr
            }
        }
    }

Note the eerie similarities :)

-Steve

Reply via email to