Skip to content

Commit 3f46e3c

Browse files
committed
Break reference cycle in NimGodotObject
1 parent 87707a8 commit 3f46e3c

File tree

2 files changed

+12
-4
lines changed

2 files changed

+12
-4
lines changed

godot.nimble

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
version = "0.7.28"
1+
version = "0.8.0"
22
author = "Xored Software, Inc."
33
description = "Godot Engine bindings"
44
license = "MIT"

godot/nim/godotnim.nim

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,14 +31,16 @@ type
3131
## The base type all Godot types inherit from.
3232
## Manages lifecycle of the wrapped ``GodotObject``.
3333
godotObject: ptr GodotObject
34-
linkedObject: NimGodotObject
34+
linkedObjectPtr: pointer
3535
## Wrapper around native object that is the container of the Nim "script"
3636
## This is needed for `of` checks and `as` conversions to work as
3737
## expected. For example, Nim type may inherit from ``Spatial``, but the
3838
## script is attached to ``Particles``. In this case conversion to
3939
## ``Particles`` is valid, but Nim type system is not aware of that.
4040
## This works in both directions - for linked native object this
4141
## reference points to Nim object.
42+
## This is stored as a raw pointer to avoid reference cycles and therefore
43+
## improve GC performance.
4244
isRef*: bool
4345
isFinalized: bool
4446
isNative: bool
@@ -185,6 +187,9 @@ proc deinit*(obj: NimGodotObject) =
185187
obj.godotObject.deinit()
186188
obj.godotObject = nil
187189

190+
proc linkedObject(obj: NimGodotObject): NimGodotObject {.inline.} =
191+
cast[NimGodotObject](obj.linkedObjectPtr)
192+
188193
proc nimGodotObjectFinalizer*[T: NimGodotObject](obj: T) =
189194
if obj.godotObject.isNil or obj.isNative: return
190195
# important to set it before so that ``unreference`` is aware
@@ -465,14 +470,17 @@ proc setGodotObject*(nimObj: NimGodotObject, obj: ptr GodotObject) {.inline.} =
465470
proc setNativeObject*(nimObj: NimGodotObject,
466471
nativeObj: NimGodotObject) {.inline.} =
467472
## Used from Godot constructor produced by ``gdobj`` macro. Do not call.
468-
nimObj.linkedObject = nativeObj
469-
nativeObj.linkedObject = nimObj
473+
GC_ref(nativeObj)
474+
nimObj.linkedObjectPtr = cast[pointer](nativeObj)
475+
nativeObj.linkedObjectPtr = cast[pointer](nimObj)
470476
nativeObj.isNative = true
471477

472478
proc removeGodotObject*(nimObj: NimGodotObject) {.inline.} =
473479
## Used from Godot destructor produced by ``gdobj`` macro. Do not call.
480+
GC_unref(nimObj.linkedObject)
474481
nimObj.godotObject = nil
475482
nimObj.linkedObject.godotObject = nil
483+
nimObj.linkedObjectPtr = nil
476484

477485
proc `==`*(self, other: NimGodotObject): bool {.inline.} =
478486
## Compares objects by referential equality.

0 commit comments

Comments
 (0)