www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - IUnknown & gc

reply "Ilya Zaitseff" <sarkseven gmail.com> writes:
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?
Oct 16 2005
parent reply "John C" <johnch_atms hotmail.com> writes:
"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.
Oct 17 2005
parent "Artem Rebrov" <ar_other mail.ru> writes:
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/
Oct 17 2005