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
+ 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
+
3
69
static ID id_gcguard_table ;
4
70
static PyObject * weakref_callback_pyobj ;
5
71
static PyObject * gcguard_weakref_destroyed (PyObject * self , PyObject * weakref );
@@ -21,15 +87,15 @@ gcguard_weakref_destroyed(PyObject *self, PyObject *weakref)
21
87
void
22
88
pycall_gcguard_aset (PyObject * pyobj , VALUE rbobj )
23
89
{
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 );
26
92
}
27
93
28
94
void
29
95
pycall_gcguard_delete (PyObject * pyobj )
30
96
{
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 );
33
99
}
34
100
35
101
void
@@ -64,11 +130,21 @@ pycall_gcguard_register(PyObject *pyobj, VALUE obj)
64
130
pycall_gcguard_aset (wref , obj );
65
131
}
66
132
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
+
67
143
void
68
144
pycall_init_gcguard (void )
69
145
{
70
146
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 ());
72
148
73
149
weakref_callback_pyobj = Py_API (PyCFunction_NewEx )(& gcguard_weakref_callback_def , NULL , NULL );
74
150
}
0 commit comments