Thread overview
IUnknown & gc
Oct 16, 2005
Ilya Zaitseff
Oct 17, 2005
John C
Oct 17, 2005
Artem Rebrov
October 16, 2005
Currently I'm writing a COM-like thing in D.

Good news that D makes interface with +0 offset for methods in vtable for any interface named IUnknown. I can't say that I like that way, but it works. <g>

But I have several questions for COM interface memory management.

IUnknown subclasses allocates through c.malloc, not gc one:
(internal/gc/gc.d]
Object _d_newclass(ClassInfo ci)
  ...
  if (ci.flags & 1)			// if COM object
  {
    p = cast(Object)std.c.stdlib.malloc(ci.init.length);

But in ComObject class implementating IUnknown, in destrustor we see:
[std.c.windows.com]
ULONG Release()
{
  ...
  if (lRef == 0)
  {
    // free object

    // If we delete this object, then the postinvariant called upon
    // return from Release() will fail.
    // Just let the GC reap it.

    //delete this;
    return 0;
  }

std.windows.iunknown don't explicitly deletes this, too.

But gc will never reap it, isn't it?

And, I'm interesting, how will be handled gc-ed classes that I allocate in COM-class?
October 17, 2005
"Ilya Zaitseff" <sarkseven@gmail.com> wrote in message news:op.syrdonmnegdzq7@ilya.tec.amursk.ru...
> Currently I'm writing a COM-like thing in D.
>
> Good news that D makes interface with +0 offset for methods in vtable for any interface named IUnknown. I can't say that I like that way, but it works. <g>
>
> But I have several questions for COM interface memory management.
>
> IUnknown subclasses allocates through c.malloc, not gc one:
> (internal/gc/gc.d]
> Object _d_newclass(ClassInfo ci)
>   ...
>   if (ci.flags & 1) // if COM object
>   {
>     p = cast(Object)std.c.stdlib.malloc(ci.init.length);
>
> But in ComObject class implementating IUnknown, in destrustor we see:
> [std.c.windows.com]
> ULONG Release()
> {
>   ...
>   if (lRef == 0)
>   {
>     // free object
>
>     // If we delete this object, then the postinvariant called upon
>     // return from Release() will fail.
>     // Just let the GC reap it.
>
>     //delete this;
>     return 0;
>   }
>
> std.windows.iunknown don't explicitly deletes this, too.
>
> But gc will never reap it, isn't it?
>
> And, I'm interesting, how will be handled gc-ed classes that I allocate in COM-class?

In my tests, normal class objects new'd by IUnknown-derived classes are garbage collected as you'd expect.

If the memory allocated by _d_newclass isn't freed, then it's safe to assume you're leaking memory. However, I've experienced problems when explicitly freeing COM objects via std.c.stdlib.free (for example, other objects held by COM objects don't get GC'd).

I don't know what the solution is. Perhaps Walter can explain how to safely use COM objects in D.


October 17, 2005
I think the possible solution is like this:
1) Let COM objects to be a gc-collected.
2) Add a gc-roots for these objects
      in [internal/gc/gc.d] in _d_newclass
or
	in [std.c.windows.com] in ctor of ComObject
3) Remove gc-roots in ComObject.Release() when reference count is equal to zero.

On Mon, 17 Oct 2005 15:34:12 +0400, John C <johnch_atms@hotmail.com> wrote:
> "Ilya Zaitseff" <sarkseven@gmail.com> wrote in message
> news:op.syrdonmnegdzq7@ilya.tec.amursk.ru...
>> IUnknown subclasses allocates through c.malloc, not gc one:
>> (internal/gc/gc.d]
>> Object _d_newclass(ClassInfo ci)
>>   ...
>>   if (ci.flags & 1) // if COM object
>>   {
>>     p = cast(Object)std.c.stdlib.malloc(ci.init.length);
>>
>> But in ComObject class implementating IUnknown, in destrustor we see:
>> [std.c.windows.com]
>> ULONG Release()
>> {
>>   ...
>>   if (lRef == 0)
>>   {
>>     // free object
>>
>>     // If we delete this object, then the postinvariant called upon
>>     // return from Release() will fail.
>>     // Just let the GC reap it.
>>
>>     //delete this;
>>     return 0;
>>   }
>>
>> std.windows.iunknown don't explicitly deletes this, too.
>>
>> But gc will never reap it, isn't it?
>>
>> And, I'm interesting, how will be handled gc-ed classes that I allocate in
>> COM-class?
>
> In my tests, normal class objects new'd by IUnknown-derived classes are
> garbage collected as you'd expect.
>
> If the memory allocated by _d_newclass isn't freed, then it's safe to assume
> you're leaking memory. However, I've experienced problems when explicitly
> freeing COM objects via std.c.stdlib.free (for example, other objects held
> by COM objects don't get GC'd).
>
> I don't know what the solution is. Perhaps Walter can explain how to safely
> use COM objects in D.

-- 
Using Opera's revolutionary e-mail client: http://www.opera.com/mail/