diff --git a/pkgs/racket-doc/scribblings/foreign/pointers.scrbl b/pkgs/racket-doc/scribblings/foreign/pointers.scrbl index 673961584e..bbaea50663 100644 --- a/pkgs/racket-doc/scribblings/foreign/pointers.scrbl +++ b/pkgs/racket-doc/scribblings/foreign/pointers.scrbl @@ -57,8 +57,18 @@ offset is always in bytes.} @defproc[(cpointer-gcable? [cptr cpointer?]) boolean?]{ Returns @racket[#t] if @racket[cptr] is treated as a reference to -memory that is managed by the garbage collector, @racket[#f] -otherwise.} +memory that is (assumed to be) managed by the garbage collector, +@racket[#f] otherwise. + +For a pointer based on @racket[_gcpointer] as a result type, +@racket[cpointer-gcable?] will return @racket[#t]. In the @3m[] and +@CGC[] variants of Racket, @racket[cpointer-gcable?] will return +@racket[#f] for a pointer based on @racket[_pointer] as a result type. +The @CS[] variant is mostly the sane, except that if a pointer is +extracted using the @racket[_pointer] type from memory allocated as +@racket['nonatomic], @racket[cpointer-gcable?] will report @racket[#t] +for the extracted pointer.} + @; ---------------------------------------------------------------------- @@ -466,12 +476,12 @@ use by such finalizers.} @defproc[(make-sized-byte-string [cptr cpointer?] [length exact-nonnegative-integer?]) bytes?]{ -Returns a byte string made of the given pointer and the given length. -No copying is performed. Beware that future implementations of Racket -may not support this function (in case of a byte string representation -that combines a size and byte-string content without an indirection). +Returns a byte string made of the given pointer and the given length +in the @3m[] and @CGC[] variants of Racket; no copying is performed. +In the @CS[] variant, the @racket[exn:fail:unsupported] exception is +raised. -Beware also that the representation of a Racket byte string normally +Beware that the representation of a Racket byte string normally requires a nul terminator at the end of the byte string (after @racket[length] bytes), but some functions work with a byte-string representation that has no such terminator---notably diff --git a/pkgs/racket-doc/scribblings/foreign/types.scrbl b/pkgs/racket-doc/scribblings/foreign/types.scrbl index dbd47764b5..5b66dac137 100644 --- a/pkgs/racket-doc/scribblings/foreign/types.scrbl +++ b/pkgs/racket-doc/scribblings/foreign/types.scrbl @@ -418,11 +418,13 @@ See @secref["foreign:tagged-pointers"] for creating pointer types that use these tags for safety. A @racket[#f] value is converted to @cpp{NULL} and vice versa. -The address referenced by a @racket[_pointer] value must not refer to +As a result type, the address referenced by a @racket[_pointer] value must not refer to memory managed by the garbage collector (unless the address corresponds to a value that supports interior pointers and that is otherwise referenced to preserve the value from garbage collection). The reference is not traced or updated by the garbage collector. +As an argument type, @racket[_pointer] works for a reference to either +GC-managed memory or not. The @racket[equal?] predicate equates C pointers (including pointers for @racket[_gcpointer] and possibly containing an offset) when they @@ -433,11 +435,13 @@ case the equality rules of the relevant structure types apply.} @defthing[_gcpointer ctype?]{ -Like @racket[_pointer], but for a C pointer value that can refer to memory -managed by the garbage collector. +The same as @racket[_pointer] as an argument type, but as a result +type, @racket[_gcpointer] corresponds to a C pointer value that refers +to memory managed by the garbage collector. -Although a @racket[_gcpointer] can reference to memory that is not -managed by the garbage collector, beware of using an address that +In the @3m[] and @CGC[] variants of Racket, a @racket[_gcpointer] result +pointer can reference to memory that is not +managed by the garbage collector, but beware of using an address that might eventually become managed by the garbage collector. For example, if a reference is created by @racket[malloc] with @racket['raw] and released by @racket[free], then the @racket[free] may allow the memory @@ -445,9 +449,8 @@ formerly occupied by the reference to be used later by the garbage collector. The @racket[cpointer-gcable?] function returns @racket[#t] for a -cpointer generated via the @racket[_gcpointer] type, while it -generates @racket[#f] for a cpointer generated via the -@racket[_cpointer] type.} +cpointer generated via the @racket[_gcpointer] result type. See +@racket[cpointer-gcable?] for more information.} @deftogether[( @@ -1141,10 +1144,13 @@ type; a byte string is passed as @racket[_bytes] without any copying. Beware that a Racket byte string is not necessarily nul terminated; see also @racket[_bytes/nul-terminated]. -In the @3m[] and @CGC[] variants of Racket, a C non-NULL @cpp{char*} -is converted to a Racket byte string without copying. In the @CS[] -variant, conversion requires copying to represent a C @cpp{char*} -result as a Racket byte string. In both cases, the C result must have +In the @3m[] and @CGC[] variants of Racket, a C non-NULL result value +is converted to a Racket byte string without copying; the pointer is +treated as potentially managed by the garbage collector (see +@racket[_gcpointer] for caveats). In the @CS[] variant of Racket, +conversion requires copying to represent a C @cpp{char*} +result as a Racket byte string, and the original pointer is @emph{not} +treated as managed by the garbage collector. In both cases, the C result must have a nul terminator to determine the Racket byte string's length. A @racket[(_bytes o len-expr)] form is a @tech{custom function type}. @@ -1182,6 +1188,7 @@ results. @history[#:added "6.12.0.2"]} + @; ------------------------------------------------------------ @section{C Struct Types} diff --git a/racket/collects/ffi/unsafe.rkt b/racket/collects/ffi/unsafe.rkt index 25873c9de5..60dff0b854 100644 --- a/racket/collects/ffi/unsafe.rkt +++ b/racket/collects/ffi/unsafe.rkt @@ -1114,6 +1114,13 @@ pre: (x => (vector->cblock x t)) post: (x => (cblock->vector x t n)))])) +;; Reflect the difference between 'racket and 'chez-scheme +;; VMs for `_bytes` in `_bytes*`: +(define _pointer/maybe-gcable + (if (eq? 'racket (system-type 'vm)) + _gcpointer + _pointer)) + ;; _bytes or (_bytes o n) is for a memory block represented as a Scheme byte ;; string. _bytes is just like a byte-string, and (_bytes o n) is for ;; pre-malloc of the string. There is no need for other modes: i or io would @@ -1123,7 +1130,7 @@ (provide (rename-out [_bytes* _bytes])) (define-fun-syntax _bytes* (syntax-id-rules (o) - [(_ o n) (type: _gcpointer + [(_ o n) (type: _pointer/maybe-gcable pre: (make-bytes-argument n) ;; post is needed when this is used as a function output type post: (x => (receive-bytes-result x n)))] diff --git a/racket/collects/file/resource.rkt b/racket/collects/file/resource.rkt index 61db9bd759..03b89a52e4 100644 --- a/racket/collects/file/resource.rkt +++ b/racket/collects/file/resource.rkt @@ -268,9 +268,8 @@ (define (to-utf-16 s) (let ([v (malloc _gcpointer)]) (ptr-set! v _string/utf-16 s) - (let ([p (ptr-ref v _gcpointer)]) - (let ([len (* 2 (+ 1 (utf-16-length s)))]) - (ptr-ref v (_bytes o len)))))) + (let ([len (* 2 (+ 1 (utf-16-length s)))]) + (ptr-ref v (_bytes o len))))) (define (utf-16-length s) (for/fold ([len 0]) ([c (in-string s)])