Seems simplest to be to have typed racket know to trust register finalizer and thus avoid wrapping it with a contract. <div><br></div><div>Robby<span></span><br><br>On Saturday, August 16, 2014, Neil Toronto <<a href="mailto:neil.toronto@gmail.com">neil.toronto@gmail.com</a>> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Short version: the contract system doesn't allow `register-finalizer` to be used in Typed Racket.<br>
<br>
Long version: consider the following Typed Racket program, in which instances of `os-resource-wrapper` represent an operating system resource `os-resource`, which itself is just a counter. It attempts to register a finalizer for allocated wrappers, which decrements the counter.<br>
<br>
<br>
#lang typed/racket<br>
<br>
(require/typed<br>
ffi/unsafe<br>
[register-finalizer (All (A) (-> A (-> A Any) Void))])<br>
<br>
(: os-resource Integer)<br>
(define os-resource 0)<br>
<br>
(struct os-resource-wrapper ())<br>
<br>
(: alloc-os-resource (-> os-resource-wrapper))<br>
(define (alloc-os-resource)<br>
(set! os-resource (add1 os-resource))<br>
(define w (os-resource-wrapper))<br>
(register-finalizer w (λ (w) (set! os-resource (sub1 os-resource))))<br>
w)<br>
<br>
(define w (alloc-os-resource))<br>
(printf "os-resource = ~v~n" os-resource)<br>
(collect-garbage)<br>
(sleep 1) ; give finalizers a chance to run<br>
(printf "os-resource = ~v~n" os-resource)<br>
<br>
<br>
I get this output:<br>
<br>
os-resource = 1<br>
os-resource = 0<br>
<br>
The finalizer is being run while the program still has a pointer to the wrapper object. I think it's because the wrapper object is being impersonated when it's sent across the contract barrier, and the *impersonator* is getting the finalizer. (Or it's a chaperone, or an impostor, or a charlatan, or whatever. Let's go with impersonator.)<br>
<br>
In my specific case, the OS resources are OpenGL objects; e.g. vertex object arrays. The call to `register-finalizer` *must* be in Typed Racket code because the wrapper contains an (Instance GL-Context<%>), which can't have a contract put on it, so it can't pass from untyped to typed code.<br>
<br>
Is there any reason for `register-finalizer` to behave this way? Does it ever make sense to register a finalizer on an impersonator?<br>
<br>
Neil ⊥<br>
_________________________<br>
Racket Developers list:<br>
<a href="http://lists.racket-lang.org/dev" target="_blank">http://lists.racket-lang.org/<u></u>dev</a><br>
</blockquote></div>