11#include "pycall_internal.h"
22
3+ struct gcguard {
4+ st_table * guarded_objects ;
5+ };
6+
7+ static int
8+ gcguard_mark_i (st_data_t key , st_data_t val , st_data_t arg )
9+ {
10+ VALUE obj = (VALUE )val ;
11+ rb_gc_mark (obj );
12+ return ST_CONTINUE ;
13+ }
14+
15+ static void
16+ gcguard_mark (void * ptr )
17+ {
18+ struct gcguard * gg = (struct gcguard * )ptr ;
19+ st_foreach (gg -> guarded_objects , gcguard_mark_i , 0 );
20+ }
21+
22+ static void
23+ gcguard_free (void * ptr )
24+ {
25+ struct gcguard * gg = (struct gcguard * )ptr ;
26+ st_free_table (gg -> guarded_objects );
27+ }
28+
29+ static size_t
30+ gcguard_memsize (const void * ptr )
31+ {
32+ const struct gcguard * gg = (const struct gcguard * )ptr ;
33+ return st_memsize (gg -> guarded_objects );
34+ }
35+
36+ static rb_data_type_t gcguard_data_type = {
37+ "PyCall::gcguard" ,
38+ {
39+ gcguard_mark ,
40+ gcguard_free ,
41+ gcguard_memsize ,
42+ },
43+ #ifdef RUBY_TYPED_FREE_IMMEDIATELY
44+ 0 , 0 , RUBY_TYPED_FREE_IMMEDIATELY
45+ #endif
46+ };
47+
48+ static void
49+ gcguard_aset (VALUE gcguard , PyObject * pyptr , VALUE rbobj )
50+ {
51+ struct gcguard * gg ;
52+ TypedData_Get_Struct (gcguard , struct gcguard , & gcguard_data_type , gg );
53+
54+ st_insert (gg -> guarded_objects , (st_data_t )pyptr , (st_data_t )rbobj );
55+ }
56+
57+ static void
58+ gcguard_delete (VALUE gcguard , PyObject * pyptr )
59+ {
60+ struct gcguard * gg ;
61+ st_data_t key , val ;
62+
63+ TypedData_Get_Struct (gcguard , struct gcguard , & gcguard_data_type , gg );
64+
65+ key = (st_data_t )pyptr ;
66+ st_delete (gg -> guarded_objects , & key , & val );
67+ }
68+
369static ID id_gcguard_table ;
470static PyObject * weakref_callback_pyobj ;
571static PyObject * gcguard_weakref_destroyed (PyObject * self , PyObject * weakref );
@@ -21,15 +87,15 @@ gcguard_weakref_destroyed(PyObject *self, PyObject *weakref)
2187void
2288pycall_gcguard_aset (PyObject * pyobj , VALUE rbobj )
2389{
24- VALUE table = rb_ivar_get (mPyCall , id_gcguard_table );
25- rb_hash_aset ( table , PTR2NUM ( pyobj ) , rbobj );
90+ VALUE gcguard = rb_ivar_get (mPyCall , id_gcguard_table );
91+ gcguard_aset ( gcguard , pyobj , rbobj );
2692}
2793
2894void
2995pycall_gcguard_delete (PyObject * pyobj )
3096{
31- VALUE table = rb_ivar_get (mPyCall , id_gcguard_table );
32- rb_hash_delete ( table , PTR2NUM ( pyobj ) );
97+ VALUE gcguard = rb_ivar_get (mPyCall , id_gcguard_table );
98+ gcguard_delete ( gcguard , pyobj );
3399}
34100
35101void
@@ -64,11 +130,21 @@ pycall_gcguard_register(PyObject *pyobj, VALUE obj)
64130 pycall_gcguard_aset (wref , obj );
65131}
66132
133+ static VALUE
134+ gcguard_new (void )
135+ {
136+ struct gcguard * gg ;
137+ VALUE obj = TypedData_Make_Struct (0 , struct gcguard , & gcguard_data_type , gg );
138+ gg -> guarded_objects = st_init_numtable ();
139+
140+ return obj ;
141+ }
142+
67143void
68144pycall_init_gcguard (void )
69145{
70146 id_gcguard_table = rb_intern ("gcguard_table" );
71- rb_ivar_set (mPyCall , id_gcguard_table , rb_hash_new ());
147+ rb_ivar_set (mPyCall , id_gcguard_table , gcguard_new ());
72148
73149 weakref_callback_pyobj = Py_API (PyCFunction_NewEx )(& gcguard_weakref_callback_def , NULL , NULL );
74150}
0 commit comments