@@ -83,11 +83,50 @@ enable(on::Bool) = ccall(:jl_gc_enable, Int32, (Int32,), on) != 0
8383"""
8484 GC.@preserve x1 x2 ... xn expr
8585
86- Temporarily protect the given objects from being garbage collected, even if they would
87- otherwise be unreferenced.
88-
89- The last argument is the expression during which the object(s) will be preserved.
90- The previous arguments are the objects to preserve.
86+ Mark the objects `x1, x2, ...` as being *in use* during the evaluation of the
87+ expression `expr`. This is only required in unsafe code where `expr`
88+ *implicitly uses* memory or other resources owned by one of the `x`s.
89+
90+ *Implicit use* of `x` covers any indirect use of resources logically owned by
91+ `x` which the compiler cannot see. Some examples:
92+ * Accessing memory of an object directly via a `Ptr`
93+ * Passing a pointer to `x` to `ccall`
94+ * Using resources of `x` which would be cleaned up in the finalizer.
95+
96+ `@preserve` should generally not have any performance impact in typical use
97+ cases where it briefly extends object lifetime. In implementation, `@preserve`
98+ has effects such as protecting dynamically allocated objects from garbage
99+ collection.
100+
101+ # Examples
102+
103+ When loading from a pointer with `unsafe_load`, the underlying object is
104+ implicitly used, for example `x` is implicitly used by `unsafe_load(p)` in the
105+ following:
106+
107+ ```jldoctest
108+ julia> let
109+ x = Ref{Int}(101)
110+ p = Base.unsafe_convert(Ptr{Int}, x)
111+ GC.@preserve x unsafe_load(p)
112+ end
113+ 101
114+ ```
115+
116+ When passing pointers to `ccall`, the pointed-to object is implicitly used and
117+ should be preserved. (Note however that you should normally just pass `x`
118+ directly to `ccall` which counts as an explicit use.)
119+
120+ ```jldoctest
121+ julia> let
122+ x = "Hello"
123+ p = pointer(x)
124+ GC.@preserve x @ccall strlen(p::Cstring)::Cint
125+ # Preferred alternative
126+ @ccall strlen(x::Cstring)::Cint
127+ end
128+ 5
129+ ```
91130"""
92131macro preserve (args... )
93132 syms = args[1 : end - 1 ]
0 commit comments