forked from JuliaLang/julia
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgcutils.jl
180 lines (147 loc) · 5.27 KB
/
gcutils.jl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
# This file is a part of Julia. License is MIT: https://julialang.org/license
==(w::WeakRef, v::WeakRef) = isequal(w.value, v.value)
==(w::WeakRef, v) = isequal(w.value, v)
==(w, v::WeakRef) = isequal(w, v.value)
"""
finalizer(f, x)
Register a function `f(x)` to be called when there are no program-accessible references to
`x`, and return `x`. The type of `x` must be a `mutable struct`, otherwise the behavior of
this function is unpredictable.
`f` must not cause a task switch, which excludes most I/O operations such as `println`.
Using the `@async` macro (to defer context switching to outside of the finalizer) or
`ccall` to directly invoke IO functions in C may be helpful for debugging purposes.
# Examples
```julia
finalizer(my_mutable_struct) do x
@async println("Finalizing \$x.")
end
finalizer(my_mutable_struct) do x
ccall(:jl_safe_printf, Cvoid, (Cstring, Cstring), "Finalizing %s.", repr(x))
end
```
A finalizer may be registered at object construction. In the following example note that
we implicitly rely on the finalizer returning the newly created mutable struct `x`.
# Example
```julia
mutable struct MyMutableStruct
bar
function MyMutableStruct(bar)
x = new(bar)
f(t) = @async println("Finalizing \$t.")
finalizer(f, x)
end
end
```
"""
function finalizer(@nospecialize(f), @nospecialize(o))
if !ismutable(o)
error("objects of type ", typeof(o), " cannot be finalized")
end
ccall(:jl_gc_add_finalizer_th, Cvoid, (Ptr{Cvoid}, Any, Any),
Core.getptls(), o, f)
return o
end
function finalizer(f::Ptr{Cvoid}, o::T) where T
@_inline_meta
if !ismutable(o)
error("objects of type ", typeof(o), " cannot be finalized")
end
ccall(:jl_gc_add_ptr_finalizer, Cvoid, (Ptr{Cvoid}, Any, Ptr{Cvoid}),
Core.getptls(), o, f)
return o
end
"""
finalize(x)
Immediately run finalizers registered for object `x`.
"""
finalize(@nospecialize(o)) = ccall(:jl_finalize_th, Cvoid, (Ptr{Cvoid}, Any,),
Core.getptls(), o)
"""
Base.GC
Module with garbage collection utilities.
"""
module GC
# mirrored from julia.h
const GC_AUTO = 0
const GC_FULL = 1
const GC_INCREMENTAL = 2
"""
GC.gc([full=true])
Perform garbage collection. The argument `full` determines the kind of
collection: A full collection (default) sweeps all objects, which makes the
next GC scan much slower, while an incremental collection may only sweep
so-called young objects.
!!! warning
Excessive use will likely lead to poor performance.
"""
gc(full::Bool=true) =
ccall(:jl_gc_collect, Cvoid, (Cint,), full ? GC_FULL : GC_INCREMENTAL)
"""
GC.enable(on::Bool)
Control whether garbage collection is enabled using a boolean argument (`true` for enabled,
`false` for disabled). Return previous GC state.
!!! warning
Disabling garbage collection should be used only with caution, as it can cause memory
use to grow without bound.
"""
enable(on::Bool) = ccall(:jl_gc_enable, Int32, (Int32,), on) != 0
"""
GC.@preserve x1 x2 ... xn expr
Mark the objects `x1, x2, ...` as being *in use* during the evaluation of the
expression `expr`. This is only required in unsafe code where `expr`
*implicitly uses* memory or other resources owned by one of the `x`s.
*Implicit use* of `x` covers any indirect use of resources logically owned by
`x` which the compiler cannot see. Some examples:
* Accessing memory of an object directly via a `Ptr`
* Passing a pointer to `x` to `ccall`
* Using resources of `x` which would be cleaned up in the finalizer.
`@preserve` should generally not have any performance impact in typical use
cases where it briefly extends object lifetime. In implementation, `@preserve`
has effects such as protecting dynamically allocated objects from garbage
collection.
# Examples
When loading from a pointer with `unsafe_load`, the underlying object is
implicitly used, for example `x` is implicitly used by `unsafe_load(p)` in the
following:
```jldoctest
julia> let
x = Ref{Int}(101)
p = Base.unsafe_convert(Ptr{Int}, x)
GC.@preserve x unsafe_load(p)
end
101
```
When passing pointers to `ccall`, the pointed-to object is implicitly used and
should be preserved. (Note however that you should normally just pass `x`
directly to `ccall` which counts as an explicit use.)
```jldoctest
julia> let
x = "Hello"
p = pointer(x)
Int(GC.@preserve x @ccall strlen(p::Cstring)::Csize_t)
# Preferred alternative
Int(@ccall strlen(x::Cstring)::Csize_t)
end
5
```
"""
macro preserve(args...)
syms = args[1:end-1]
for x in syms
isa(x, Symbol) || error("Preserved variable must be a symbol")
end
esc(Expr(:gc_preserve, args[end], syms...))
end
"""
GC.safepoint()
Inserts a point in the program where garbage collection may run.
This can be useful in rare cases in multi-threaded programs where some threads
are allocating memory (and hence may need to run GC) but other threads are doing
only simple operations (no allocation, task switches, or I/O).
Calling this function periodically in non-allocating threads allows garbage
collection to run.
!!! compat "Julia 1.4"
This function is available as of Julia 1.4.
"""
safepoint() = ccall(:jl_gc_safepoint, Cvoid, ())
end # module GC