I'm dealing with some foreign apis that want to be passed long lived output
pointers to structs. The apis eventually call back indicating that the
struct has been filled in appropriately and then I want to read out the
values and deallocate the structs. I'm using atomic interior memory for
these structs as they don't need to hold GCable values themselves and they
need to not be moved while the foreign library has a pointer to them. Once
they are back I need to construct derived pointers to the sub structs and
parse out all the different parameters.

The issue I'm running into is reliably destroying the struct when I'm done
parsing out all the values. If it was as simple as freeing the memory, it
would be easy as I can rely on the GC to do that. But it is not as the
struct has pointer fields that may have been initialized by the foreign
library and thus I need to actively run destructor code to free those
subparts before freeing the struct. This seems like a good use for
will-executors, but the issue with those is that they are attached to
racket values not the underlying memory object. And in this case because
the memory is allocated with 'atomic-interior', it is possible for the
original pointer to no longer be needed and only derived pointers needed.

I'm thinking there may be clever ways with making sure that every derived
pointer either maintains an explicit reference or increments a reference
count on the original pointer, but I'm worried that is very complicated and
likely to be broken. The easiest solution for me would be to have something
like a will that could be attached to a 'cpointer?' value and would be
called back with a fresh 'cpointer?' value that pointed at the same address
once there were only weak references to the object. Is this possible or
does anyone see a better solution?


Example:

;; Child corresponds to a byte array
(define-cstruct _child ([ptr _pointer] [len _int])
;; Parent has two inlined children
(define-cstruct _parent ([child1 _child] [child2 _child]))

;; When the parent is to be cleaned up I need to ensure that the two
children have their 'ptr' fields passed to free.

;; The issue is in a function that wants to decompose the parent into
children pointers and use their values:
(define (child->bytes c) <elided>)
(define (parent->bytes p)
  (bytes-append (child->bytes (parent-child1 p)) #"." (child->bytes
(parent-child2 p))))

;; In this after the parent-child2 call, there is no strong reference to p
so if this was the last reference to it, GC could happen before
child->bytes was called and determine that p was unreachable and so any
wills would become ready. Thus I cannot free the underlying memory in a
will.

-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to