1
1
#include "pycall_internal.h"
2
2
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
+ if (rb_typeddata_is_kind_of (gcguard , & gcguard_data_type )) {
61
+ /* This check is necessary to avoid error on the process finalization phase */
62
+ struct gcguard * gg ;
63
+ st_data_t key , val ;
64
+
65
+ TypedData_Get_Struct (gcguard , struct gcguard , & gcguard_data_type , gg );
66
+
67
+ key = (st_data_t )pyptr ;
68
+ st_delete (gg -> guarded_objects , & key , & val );
69
+ }
70
+ }
71
+
3
72
static ID id_gcguard_table ;
4
73
static PyObject * weakref_callback_pyobj ;
5
74
static PyObject * gcguard_weakref_destroyed (PyObject * self , PyObject * weakref );
@@ -21,15 +90,15 @@ gcguard_weakref_destroyed(PyObject *self, PyObject *weakref)
21
90
void
22
91
pycall_gcguard_aset (PyObject * pyobj , VALUE rbobj )
23
92
{
24
- VALUE table = rb_ivar_get (mPyCall , id_gcguard_table );
25
- rb_hash_aset ( table , PTR2NUM ( pyobj ) , rbobj );
93
+ VALUE gcguard = rb_ivar_get (mPyCall , id_gcguard_table );
94
+ gcguard_aset ( gcguard , pyobj , rbobj );
26
95
}
27
96
28
97
void
29
98
pycall_gcguard_delete (PyObject * pyobj )
30
99
{
31
- VALUE table = rb_ivar_get (mPyCall , id_gcguard_table );
32
- rb_hash_delete ( table , PTR2NUM ( pyobj ) );
100
+ VALUE gcguard = rb_ivar_get (mPyCall , id_gcguard_table );
101
+ gcguard_delete ( gcguard , pyobj );
33
102
}
34
103
35
104
void
@@ -64,11 +133,21 @@ pycall_gcguard_register(PyObject *pyobj, VALUE obj)
64
133
pycall_gcguard_aset (wref , obj );
65
134
}
66
135
136
+ static VALUE
137
+ gcguard_new (void )
138
+ {
139
+ struct gcguard * gg ;
140
+ VALUE obj = TypedData_Make_Struct (0 , struct gcguard , & gcguard_data_type , gg );
141
+ gg -> guarded_objects = st_init_numtable ();
142
+
143
+ return obj ;
144
+ }
145
+
67
146
void
68
147
pycall_init_gcguard (void )
69
148
{
70
149
id_gcguard_table = rb_intern ("gcguard_table" );
71
- rb_ivar_set (mPyCall , id_gcguard_table , rb_hash_new ());
150
+ rb_ivar_set (mPyCall , id_gcguard_table , gcguard_new ());
72
151
73
152
weakref_callback_pyobj = Py_API (PyCFunction_NewEx )(& gcguard_weakref_callback_def , NULL , NULL );
74
153
}
0 commit comments