File tree Expand file tree Collapse file tree 4 files changed +54
-7
lines changed
Expand file tree Collapse file tree 4 files changed +54
-7
lines changed Original file line number Diff line number Diff line change @@ -36,10 +36,12 @@ func (f Func) callOneArg(arg Objecter) Object {
3636}
3737
3838func (f Func ) CallObject (args Tuple ) Object {
39+ defer getCurrentThreadData ().decRefObjectsIfNeeded ()
3940 return newObject (C .PyObject_CallObject (f .obj , args .obj ))
4041}
4142
4243func (f Func ) CallObjectKw (args Tuple , kw KwArgs ) Object {
44+ defer getCurrentThreadData ().decRefObjectsIfNeeded ()
4345 // Convert keyword arguments to Python dict
4446 kwDict := MakeDict (nil )
4547 for k , v := range kw {
@@ -51,6 +53,7 @@ func (f Func) CallObjectKw(args Tuple, kw KwArgs) Object {
5153func (f Func ) Call (args ... any ) Object {
5254 argsTuple , kwArgs := splitArgs (args ... )
5355 if kwArgs == nil {
56+ defer getCurrentThreadData ().decRefObjectsIfNeeded ()
5457 switch len (args ) {
5558 case 0 :
5659 return f .callNoArgs ()
Original file line number Diff line number Diff line change @@ -15,6 +15,7 @@ import (
1515// the Python Object's DecRef method during garbage collection.
1616type pyObject struct {
1717 obj * C.PyObject
18+ gid int64
1819}
1920
2021func (obj * pyObject ) Obj () * PyObject {
@@ -54,11 +55,12 @@ func newObject(obj *PyObject) Object {
5455 C .PyErr_Print ()
5556 panic ("nil Python object" )
5657 }
57- o := & pyObject {obj : obj }
58+ o := & pyObject {obj : obj , gid : getThreadID () }
5859 p := Object {o }
60+
5961 runtime .SetFinalizer (o , func (o * pyObject ) {
60- // TODO: need better auto-release mechanism
61- // C.Py_DecRef (o.obj)
62+ maps := getThreadData ( o . gid )
63+ maps . addPyObject (o .obj )
6264 })
6365 return p
6466}
Original file line number Diff line number Diff line change @@ -21,9 +21,9 @@ func Initialize() {
2121}
2222
2323func Finalize () {
24+ cleanupThreadLocal ()
2425 r := C .Py_FinalizeEx ()
2526 check (r == 0 , "failed to finalize Python" )
26- cleanupThreadLocal ()
2727}
2828
2929// ----------------------------------------------------------------------------
Original file line number Diff line number Diff line change @@ -35,17 +35,59 @@ func (l *holderList) Remove(holder *objectHolder) {
3535 }
3636}
3737
38+ type decRefList struct {
39+ objects []* C.PyObject
40+ mu sync.Mutex
41+ }
42+
43+ func (l * decRefList ) add (obj * C.PyObject ) {
44+ l .mu .Lock ()
45+ l .objects = append (l .objects , obj )
46+ l .mu .Unlock ()
47+ }
48+
49+ func (l * decRefList ) decRefAll () {
50+ var list []* C.PyObject
51+
52+ l .mu .Lock ()
53+ list = l .objects
54+ l .objects = make ([]* C.PyObject , 0 , maxPyObjects * 2 )
55+ l .mu .Unlock ()
56+
57+ for _ , obj := range list {
58+ C .Py_DecRef (obj )
59+ }
60+ }
61+
3862type threadData struct {
39- typeMetas map [* C.PyObject ]* typeMeta
40- pyTypes map [reflect.Type ]* C.PyObject
41- holders holderList
63+ typeMetas map [* C.PyObject ]* typeMeta
64+ pyTypes map [reflect.Type ]* C.PyObject
65+ holders holderList
66+ decRefList decRefList
67+ }
68+
69+ const maxPyObjects = 128
70+
71+ func (td * threadData ) addPyObject (obj * C.PyObject ) {
72+ td .decRefList .add (obj )
73+ }
74+
75+ func (td * threadData ) decRefObjectsIfNeeded () {
76+ if len (td .decRefList .objects ) > maxPyObjects {
77+ td .decRefList .decRefAll ()
78+ }
4279}
4380
4481var (
4582 globalThreadData sync.Map // map[int64]*threadData
4683)
4784
4885func getCurrentThreadData () * threadData {
86+ id := getThreadID ()
87+ return getThreadData (id )
88+ }
89+
90+ func getThreadData (gid int64 ) * threadData {
4991 id := getThreadID ()
5092 maps , ok := globalThreadData .Load (id )
5193 if ! ok {
You can’t perform that action at this time.
0 commit comments