Skip to content

Commit

Permalink
make PythonCall.GC more like Base.GC (#413)
Browse files Browse the repository at this point in the history
Co-authored-by: Christopher Doris <github.com/cjdoris>
  • Loading branch information
cjdoris committed Nov 7, 2023
1 parent 3ac5f4d commit 63a3e60
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 19 deletions.
4 changes: 2 additions & 2 deletions docs/src/faq.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ No.

Some rules if you are writing multithreaded code:
- Only call Python functions from the first thread.
- You probably also need to call `PythonCall.GC.disable()` on the main thread before any
threaded block of code. Remember to call `PythonCall.GC.enable()` again afterwards.
- You probably also need to call `on=PythonCall.GC.enable(false)` on the main thread before any
threaded block of code. Remember to call `PythonCall.GC.enable(on)` again afterwards.
(This is because Julia finalizers can be called from any thread.)
- Julia intentionally causes segmentation faults as part of the GC safepoint mechanism.
If unhandled, these segfaults will result in termination of the process. To enable signal handling,
Expand Down
1 change: 1 addition & 0 deletions docs/src/releasenotes.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Release Notes

## Unreleased (v1)
* `PythonCall.GC` is now more like `Base.GC`: `enable(true)` replaces `enable()`, `enable(false)` replaces `disable()`, and `gc()` is added.

## Unreleased
* `Py` is now treated as a scalar when broadcasting.
Expand Down
40 changes: 23 additions & 17 deletions src/GC/GC.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
Garbage collection of Python objects.
See `disable` and `enable`.
See [`enable`](@ref) and [`gc`](@ref).
"""
module GC

Expand All @@ -13,32 +13,39 @@ const ENABLED = Ref(true)
const QUEUE = C.PyPtr[]

"""
PythonCall.GC.disable()
PythonCall.GC.enable(on::Bool)
Disable the PythonCall garbage collector.
Control whether garbage collection of Python objects is turned on or off.
This means that whenever a Python object owned by Julia is finalized, it is not immediately
freed but is instead added to a queue of objects to free later when `enable()` is called.
Return the previous GC state.
Disabling the GC means that whenever a Python object owned by Julia is finalized, it is not
immediately freed but is instead added to a queue of objects to free later when GC is
re-enabled.
Like most PythonCall functions, you must only call this from the main thread.
"""
function disable()
ENABLED[] = false
return
function enable(on::Bool)
was_on = ENABLED[]
if on
ENABLED[] = true
if !was_on
gc()
end
else
ENABLED[] = false
end
return ans
end

"""
PythonCall.GC.enable()
Re-enable the PythonCall garbage collector.
PythonCall.GC.gc()
This frees any Python objects which were finalized while the GC was disabled, and allows
objects finalized in the future to be freed immediately.
Perform garbage collection of Python objects.
Like most PythonCall functions, you must only call this from the main thread.
"""
function enable()
ENABLED[] = true
function gc()
if !isempty(QUEUE)
C.with_gil(false) do
for ptr in QUEUE
Expand All @@ -47,9 +54,8 @@ function enable()
end
end
end
empty!(QUEUE)
end
empty!(QUEUE)
return
end

function enqueue(ptr::C.PyPtr)
Expand Down

0 comments on commit 63a3e60

Please sign in to comment.