[plt-scheme] Memory management and ?custodians
Matthew, hello again.
On 2010 Mar 3, at 21:03, Matthew Flatt wrote:
> At Wed, 3 Mar 2010 20:40:09 +0000, Norman Gray wrote:
>> I think my question boils down to: how do I (effectively) enforce an
>> ordering in the reclamation of (the Scheme_Object* wrappers of) two
>> inter-related C objects.
>> [...]
>> if the librdf_storage object is reclaimed before one of its
>> librdf_iterator objects, the library complains.
>
> I don't think you want custodians.
Ah: in that case can I ask a followup question?
In my current code I'm using the current custodian to manage C objects, via scheme_add_managed, and was asking about whether I should be using _multiple_ custodians to enforce cleanup ordering. I didn't think to mention the current custodian in my original question because I supposed it could be taken for granted.
Your answer makes me worry, though, that the use of custodians, and the use of the memory management tools in scheme/foreign, may be mutually exclusive. Using the register-finalizer pattern you suggested, my code's now working -- lots of unit tests pass -- but that could simply be coincidence, and I wonder if I'm simply misusing the two FFI approaches by trying to use them together. Is that plausible?
The other thing I'm starting to think is crucial (rather than a usefully elided detail) is that this cleanup is happening within an exit closer registered with scheme_add_atexit_closer. Processing what you've said, and thinking it through, I suspect that I basically can't enforce an ordering on the calls to custodian client functions at exit time: I'd guess that the atexit calls ignore any dependencies in order to avoid getting caught in dependency loops.
Thus I seem to be arguing myself into the position that, if I want to free/close a storage object's iterators before freeing/closing the storage object (in the parlance of my original question), and do it at exit time, then I have to enforce that ordering at the C level (messy). Am I misunderstanding what's going on here?
Thanks for any pointers (ho ho).
>> [ Parenthetically: I'm slightly surprised that the iterator isn't being freed
>> promptly, as it's inside the equivalent of:
>> (let ((storage (get-storage ...))
>> ; do stuff
>> (let ((iterator (get-iterator storage)))
>> #t)
>> (collect-garbage)
>> ; do more stuff with storage
>> )
>
> Switching to 3m could solve that problem. With CGC, it's easy for a
> dead reference to be sitting somewhere that the GC thinks is live.
I shall save this delight for the next refactoring....
Best wishes,
Norman
--
Norman Gray : http://nxg.me.uk