diff --git a/pkgs/racket-doc/scribblings/foreign/pointers.scrbl b/pkgs/racket-doc/scribblings/foreign/pointers.scrbl index aa38c44ead..6f633c6433 100644 --- a/pkgs/racket-doc/scribblings/foreign/pointers.scrbl +++ b/pkgs/racket-doc/scribblings/foreign/pointers.scrbl @@ -409,6 +409,17 @@ be used with @racket[ptr-add] to create a substring of a Racket byte string, because the offset pointer would be to the middle of a collectable object (which is not allowed).} + +@defproc[(void/reference-sink [v any/c] ...) void?]{ + +Returns @|void-const|, but unlike calling the @racket[void] function +where the compiler may optimize away the call and replace it with a +@|void-const| result, calling @racket[void/reference-sink] ensures +that the arguments are considered reachable by the garbage collector +until the call returns. + +@history[#:added "6.10.1.2"]} + @; ---------------------------------------------------------------------- @section{Pointer Structure Property} diff --git a/pkgs/racket-test-core/tests/racket/foreign-test.rktl b/pkgs/racket-test-core/tests/racket/foreign-test.rktl index 05b8a5aa83..47855876b1 100644 --- a/pkgs/racket-test-core/tests/racket/foreign-test.rktl +++ b/pkgs/racket-test-core/tests/racket/foreign-test.rktl @@ -1225,6 +1225,15 @@ ;; ---------------------------------------- +;; Check `void/reference-sink` +(let* ([sym (gensym)] + [wb (make-weak-box sym)]) + (collect-garbage) + (void/reference-sink sym) + (test #f not (weak-box-value wb))) + +;; ---------------------------------------- + (let () (unless (eq? (system-type) 'windows) (define-ffi-definer define-test-lib test-lib diff --git a/racket/collects/ffi/unsafe.rkt b/racket/collects/ffi/unsafe.rkt index c7c8248438..104c30501d 100644 --- a/racket/collects/ffi/unsafe.rkt +++ b/racket/collects/ffi/unsafe.rkt @@ -22,7 +22,8 @@ _bool _stdbool _pointer _gcpointer _scheme (rename-out [_scheme _racket]) _fpointer function-ptr memcpy memmove memset malloc-immobile-cell free-immobile-cell - make-late-weak-box make-late-weak-hasheq) + make-late-weak-box make-late-weak-hasheq + void/reference-sink) (define-syntax define* (syntax-rules () @@ -1988,3 +1989,13 @@ (let loop () (will-execute killer-executor) (loop)))))) (retry-loop))))))) (will-register killer-executor obj finalizer)))) + +;; The same as `void`, but written so that the compiler cannot +;; optimize away the call or arguments, so that calling +;; `void/reference-sink` ensures that arguments are retained. +(define* void/reference-sink + (let ([proc void]) + (case-lambda + [(v) (proc v)] + [(v1 v2) (proc v1 v2)] + [args (set! proc (lambda args (void))) (proc args)])))