Is the work to parse out the values short enough that you can do it
atomically in response to the notification that says the data is ready?
If so, it's probably best to parse and free in atomic mode. Or can you
at least atomically separate out references to children, where
finalizers can sensibly be attached to the individual references?

If not, then I don't have a better idea than the approach you describe.
I don't quite follow why you'd need new functionality from wills, since
a will procedure on a cpointer already receives the cpointer back when
there are otherwise no references to the cpointer.

At Tue, 3 Oct 2017 18:39:04 -0700, Eric Dobson wrote:
> 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.

-- 
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