11#![ allow( clippy:: missing_safety_doc) ]
22
33use std:: {
4- ffi:: { CStr , CString } ,
4+ ffi:: CStr ,
55 mem:: transmute,
6- os:: raw:: { c_char, c_int , c_void} ,
7- path:: { Path , PathBuf } ,
6+ os:: raw:: { c_char, c_void} ,
7+ path:: Path ,
88 ptr,
9- sync:: { Mutex } ,
9+ sync:: Mutex ,
1010} ;
1111
1212use rb_sys:: {
1313 rb_add_event_hook2, rb_remove_event_hook_with_data, rb_define_class,
14- rb_define_alloc_func, rb_define_method, rb_obj_alloc,
15- rb_ivar_set, rb_ivar_get, rb_intern, rb_ull2inum, rb_num2ull,
14+ rb_define_alloc_func, rb_define_method,
1615 rb_event_hook_flag_t:: RUBY_EVENT_HOOK_FLAG_RAW_ARG ,
1716 rb_event_flag_t, rb_trace_arg_t,
1817 rb_tracearg_event_flag, rb_tracearg_lineno, rb_tracearg_path,
@@ -21,23 +20,75 @@ use rb_sys::{
2120} ;
2221use runtime_tracing:: { Tracer , Line } ;
2322
23+ #[ repr( C ) ]
24+ struct RTypedData {
25+ _basic : [ VALUE ; 2 ] ,
26+ type_ : * const rb_data_type_t ,
27+ typed_flag : VALUE ,
28+ data : * mut c_void ,
29+ }
30+
31+ #[ repr( C ) ]
32+ struct rb_data_type_function_struct {
33+ dmark : Option < unsafe extern "C" fn ( * mut c_void ) > ,
34+ dfree : Option < unsafe extern "C" fn ( * mut c_void ) > ,
35+ dsize : Option < unsafe extern "C" fn ( * const c_void ) -> usize > ,
36+ dcompact : Option < unsafe extern "C" fn ( * mut c_void ) > ,
37+ reserved : [ * mut c_void ; 1 ] ,
38+ }
39+
40+ #[ repr( C ) ]
41+ struct rb_data_type_t {
42+ wrap_struct_name : * const c_char ,
43+ function : rb_data_type_function_struct ,
44+ parent : * const rb_data_type_t ,
45+ data : * mut c_void ,
46+ flags : VALUE ,
47+ }
48+
49+ extern "C" {
50+ fn rb_data_typed_object_wrap (
51+ klass : VALUE ,
52+ datap : * mut c_void ,
53+ data_type : * const rb_data_type_t ,
54+ ) -> VALUE ;
55+ fn rb_check_typeddata ( obj : VALUE , data_type : * const rb_data_type_t ) -> * mut c_void ;
56+ }
57+
2458struct Recorder {
2559 tracer : Mutex < Tracer > ,
2660 active : bool ,
2761}
2862
29- static mut PTR_IVAR : ID = 0 ;
63+ unsafe extern "C" fn recorder_free ( ptr : * mut c_void ) {
64+ if !ptr. is_null ( ) {
65+ drop ( Box :: from_raw ( ptr as * mut Recorder ) ) ;
66+ }
67+ }
68+
69+ static mut RECORDER_TYPE : rb_data_type_t = rb_data_type_t {
70+ wrap_struct_name : b"Recorder\0 " . as_ptr ( ) as * const c_char ,
71+ function : rb_data_type_function_struct {
72+ dmark : None ,
73+ dfree : Some ( recorder_free) ,
74+ dsize : None ,
75+ dcompact : None ,
76+ reserved : [ ptr:: null_mut ( ) ; 1 ] ,
77+ } ,
78+ parent : ptr:: null ( ) ,
79+ data : ptr:: null_mut ( ) ,
80+ flags : 0 as VALUE ,
81+ } ;
3082
3183unsafe fn get_recorder ( obj : VALUE ) -> * mut Recorder {
32- let val = rb_ivar_get ( obj , PTR_IVAR ) ;
33- rb_num2ull ( val ) as * mut Recorder
84+ let ty = std :: ptr :: addr_of! ( RECORDER_TYPE ) as * const rb_data_type_t ;
85+ rb_check_typeddata ( obj , ty ) as * mut Recorder
3486}
3587
3688unsafe extern "C" fn ruby_recorder_alloc ( klass : VALUE ) -> VALUE {
37- let obj = rb_obj_alloc ( klass) ;
3889 let recorder = Box :: new ( Recorder { tracer : Mutex :: new ( Tracer :: new ( "ruby" , & vec ! [ ] ) ) , active : false } ) ;
39- rb_ivar_set ( obj , PTR_IVAR , rb_ull2inum ( Box :: into_raw ( recorder ) as u64 ) ) ;
40- obj
90+ let ty = std :: ptr :: addr_of! ( RECORDER_TYPE ) as * const rb_data_type_t ;
91+ rb_data_typed_object_wrap ( klass , Box :: into_raw ( recorder ) as * mut c_void , ty )
4192}
4293
4394unsafe extern "C" fn ruby_recorder_initialize ( _self : VALUE ) -> VALUE {
@@ -89,7 +140,8 @@ unsafe extern "C" fn flush_trace(self_val: VALUE, out_dir: VALUE) -> VALUE {
89140 }
90141 }
91142 drop ( Box :: from_raw ( recorder_ptr) ) ;
92- rb_ivar_set ( self_val, PTR_IVAR , rb_ull2inum ( 0 ) ) ;
143+ let rdata = self_val as * mut RTypedData ;
144+ ( * rdata) . data = ptr:: null_mut ( ) ;
93145 rb_sys:: Qnil . into ( )
94146}
95147
@@ -130,7 +182,6 @@ unsafe extern "C" fn event_hook_raw(data: VALUE, arg: *mut rb_trace_arg_t) {
130182#[ no_mangle]
131183pub extern "C" fn Init_codetracer_ruby_recorder ( ) {
132184 unsafe {
133- PTR_IVAR = rb_intern ( b"@ptr\0 " . as_ptr ( ) as * const c_char ) ;
134185 let class = rb_define_class ( b"RubyRecorder\0 " . as_ptr ( ) as * const c_char , rb_cObject) ;
135186 rb_define_alloc_func ( class, Some ( ruby_recorder_alloc) ) ;
136187 let init_cb: unsafe extern "C" fn ( VALUE ) -> VALUE = ruby_recorder_initialize;
0 commit comments