www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Clarifcation on AA allocation

reply pragma <pragma_member pathlink.com> writes:
Is there any way to 'manually' allocate memory for an AA in D?

The problem that prompted me to ask this?  Well, I have a class that maintains a
set of HANDLES using an AA.  Ideally, I'd like to be able to free these using
the class' dtor(), but isn't there the possibility that the GC will eliminate
the AA's memory before the dtor() is even called?

I suppose I could instruct the GC to 'ignore' the AA via 'removeRange' for
safety reasons, but I'd like to know if anyone else has a more elegant solution?

- EricAnderton at yahoo
Apr 08 2006
next sibling parent reply kris <foo bar.com> writes:
pragma wrote:
 Is there any way to 'manually' allocate memory for an AA in D?
 
 The problem that prompted me to ask this?  Well, I have a class that maintains
a
 set of HANDLES using an AA.  Ideally, I'd like to be able to free these using
 the class' dtor(), but isn't there the possibility that the GC will eliminate
 the AA's memory before the dtor() is even called?

That's right. You cannot rely on any related GC-managed memory to be intact when a dtor is invoked. As Sean noted, D "death tractors" are akin to finalizers elsewhere.
 
 I suppose I could instruct the GC to 'ignore' the AA via 'removeRange' for
 safety reasons, but I'd like to know if anyone else has a more elegant
solution?

Or malloc() them into your own list, and use the AA simply as an 'alias' of sorts? Are instances of this class intended to be long-lived? Singleton, perhaps?
Apr 08 2006
parent pragma <pragma_member pathlink.com> writes:
In article <e19b2t$5th$1 digitaldaemon.com>, kris says...
pragma wrote:
 Is there any way to 'manually' allocate memory for an AA in D?
 
 The problem that prompted me to ask this?  Well, I have a class that maintains
a
 set of HANDLES using an AA.  Ideally, I'd like to be able to free these using
 the class' dtor(), but isn't there the possibility that the GC will eliminate
 the AA's memory before the dtor() is even called?

That's right. You cannot rely on any related GC-managed memory to be intact when a dtor is invoked. As Sean noted, D "death tractors" are akin to finalizers elsewhere.
 
 I suppose I could instruct the GC to 'ignore' the AA via 'removeRange' for
 safety reasons, but I'd like to know if anyone else has a more elegant
solution?

Or malloc() them into your own list, and use the AA simply as an 'alias' of sorts?

Now *that* might just work.
Are instances of this class intended to be long-lived? Singleton, perhaps?

Sadly no. The suspect code is here: http://www.dsource.org/projects/ddl/browser/trunk/ddl/omf/OMFBinary.d?rev=169 The OMFBinary class maintains a map of library names to HANDLEs for DLL's in order to resolve IMPLIB style external references. It works pretty well. Since the scope of use for any of these HANDLES is the same as the referencing binary, they should logically be disposed of at the same time. I suppose I could move the IMPLIB resolution and DLL loading out to a separate Singleton class - that might help with a lot of these design issues. After all there's no big reason why it has to stay within the OMFBinary class itself, its just more convienent that way. You've given me much to ponder. Thanks for the ideas. :) - EricAnderton at yahoo
Apr 09 2006
prev sibling next sibling parent Sean Kelly <sean f4.ca> writes:
pragma wrote:
 Is there any way to 'manually' allocate memory for an AA in D?
 
 The problem that prompted me to ask this?  Well, I have a class that maintains
a
 set of HANDLES using an AA.  Ideally, I'd like to be able to free these using
 the class' dtor(), but isn't there the possibility that the GC will eliminate
 the AA's memory before the dtor() is even called?
 
 I suppose I could instruct the GC to 'ignore' the AA via 'removeRange' for
 safety reasons, but I'd like to know if anyone else has a more elegant
solution?

I thought about this for a while and was surprised to conclude that there's no good and easy eay to do this in D. In an ideal world you could use a struct and put the cleanup code in the struct's dtor, but that's obviously not an option. If you're willing to settle for an easy solution, RAII via classes would work: class HandleWrapper { HANDLE val; this( HANDLE h) { val = h; } ~this() { CloseHandle( val ); } HANDLE opCast() { return val; } } This will give you poor locality and a good bit of memory overhead (more than twice that of the struct method), but it's a darn sight simpler than the alternatives. For a while I thought maybe something could be sorted out via an AA of static arrays or fixed-size structs and allocating classes on top of them via placement new, but this would require .isizeof (which I mistakenly submitted as an enhancement to the bug list yesterday), and would still likely either result in premature cleanup of the objects or in their dtors never being called. Also, it doesn't sit well with me that the objects would be copied around by the AA code with no copy ctor being called... even if one isn't strictly necessary in this case. The only reasonable alternative I could come up with would be to use a non-local allocator to store the handles and to simply index them via the AA in your class. But this probably isn't worth doing unless you have memory size or performance issues that can be traced back to the AA. Sean
Apr 08 2006
prev sibling next sibling parent Walter Bright <newshound digitalmars.com> writes:
pragma wrote:
 Is there any way to 'manually' allocate memory for an AA in D?

Not without reworking internal\aaA.d.
 The problem that prompted me to ask this?  Well, I have a class that maintains
a
 set of HANDLES using an AA.  Ideally, I'd like to be able to free these using
 the class' dtor(), but isn't there the possibility that the GC will eliminate
 the AA's memory before the dtor() is even called?

As long as there's an active reference to the class object, anything the class object references, including AA's, will not be free'd by the GC. Once there is no longer an active reference to class object, then the class object will be free'd along with any parts of the AA that are not referenced elsewhere, however, the order in which the class object and AA parts are free'd is undefined.
 I suppose I could instruct the GC to 'ignore' the AA via 'removeRange' for
 safety reasons, but I'd like to know if anyone else has a more elegant
solution?

If you manually allocate/deallocate the class object, then manually delete the class object (thereby invoking the class's ~this()), any referenced AA objects will not have been collected already.
Apr 08 2006
prev sibling parent Bruno Medeiros <brunodomedeirosATgmail SPAM.com> writes:
pragma wrote:
 Is there any way to 'manually' allocate memory for an AA in D?
 
 The problem that prompted me to ask this?  Well, I have a class that maintains
a
 set of HANDLES using an AA.  Ideally, I'd like to be able to free these using
 the class' dtor(), but isn't there the possibility that the GC will eliminate
 the AA's memory before the dtor() is even called?
 
 I suppose I could instruct the GC to 'ignore' the AA via 'removeRange' for
 safety reasons, but I'd like to know if anyone else has a more elegant
solution?
 
 - EricAnderton at yahoo

Actually, I don't /think/ that that (removeRange) would even work. Correct me if I'm wrong (because the docs are not that clear) but removeRange and AddRange only make the memory block not be scanned for further roots. But the management ownership (manual-MM or GC-MM) is not changed, and the array memory block may still be collected. Is that not so? -- Bruno Medeiros - CS/E student http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D
Apr 14 2006