* properties.

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40971 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
nobu 2013-05-27 18:16:05 +00:00
parent 30dbed3837
commit 40fe524bf3

View File

@ -1,80 +1,80 @@
/********************************************************************** /**********************************************************************
gc_hook.c - GC hook mechanism/ObjectSpace extender for MRI. gc_hook.c - GC hook mechanism/ObjectSpace extender for MRI.
$Author: sorah $ $Author: sorah $
created at: Tue May 28 01:34:25 2013 created at: Tue May 28 01:34:25 2013
NOTE: This extension library is not expected to exist except C Ruby. NOTE: This extension library is not expected to exist except C Ruby.
NOTE: This feature is an example usage of internal event tracing APIs. NOTE: This feature is an example usage of internal event tracing APIs.
All the files in this distribution are covered under the Ruby's All the files in this distribution are covered under the Ruby's
license (see the file COPYING). license (see the file COPYING).
**********************************************************************/ **********************************************************************/
#include "ruby/ruby.h" #include "ruby/ruby.h"
#include "ruby/debug.h" #include "ruby/debug.h"
static void static void
invoke_proc(void *data) invoke_proc(void *data)
{ {
VALUE proc = (VALUE)data; VALUE proc = (VALUE)data;
rb_proc_call(proc, rb_ary_new()); rb_proc_call(proc, rb_ary_new());
} }
static void static void
gc_start_end_i(VALUE tpval, void *data) gc_start_end_i(VALUE tpval, void *data)
{ {
rb_trace_arg_t *tparg = rb_tracearg_from_tracepoint(tpval); rb_trace_arg_t *tparg = rb_tracearg_from_tracepoint(tpval);
if (0) fprintf(stderr, "trace: %s\n", rb_tracearg_event_flag(tparg) == RUBY_INTERNAL_EVENT_GC_START ? "gc_start" : "gc_end"); if (0) fprintf(stderr, "trace: %s\n", rb_tracearg_event_flag(tparg) == RUBY_INTERNAL_EVENT_GC_START ? "gc_start" : "gc_end");
rb_postponed_job_register(0, invoke_proc, data); rb_postponed_job_register(0, invoke_proc, data);
} }
static VALUE static VALUE
set_gc_hook(VALUE rb_mObjSpace, VALUE proc, rb_event_flag_t event, const char *tp_str, const char *proc_str) set_gc_hook(VALUE rb_mObjSpace, VALUE proc, rb_event_flag_t event, const char *tp_str, const char *proc_str)
{ {
VALUE tpval; VALUE tpval;
ID tp_key = rb_intern(tp_str); ID tp_key = rb_intern(tp_str);
ID proc_key = rb_intern(proc_str); ID proc_key = rb_intern(proc_str);
if (RTEST(tpval = rb_ivar_get(rb_mObjSpace, tp_key))) { if (RTEST(tpval = rb_ivar_get(rb_mObjSpace, tp_key))) {
rb_tracepoint_disable(tpval); rb_tracepoint_disable(tpval);
rb_ivar_set(rb_mObjSpace, tp_key, Qnil); rb_ivar_set(rb_mObjSpace, tp_key, Qnil);
rb_ivar_set(rb_mObjSpace, proc_key, Qnil); rb_ivar_set(rb_mObjSpace, proc_key, Qnil);
} }
if (RTEST(proc)) { if (RTEST(proc)) {
if (!rb_obj_is_proc(proc)) { if (!rb_obj_is_proc(proc)) {
rb_raise(rb_eTypeError, "trace_func needs to be Proc"); rb_raise(rb_eTypeError, "trace_func needs to be Proc");
} }
tpval = rb_tracepoint_new(0, event, gc_start_end_i, (void *)proc); tpval = rb_tracepoint_new(0, event, gc_start_end_i, (void *)proc);
rb_ivar_set(rb_mObjSpace, tp_key, tpval); rb_ivar_set(rb_mObjSpace, tp_key, tpval);
rb_ivar_set(rb_mObjSpace, proc_key, proc); /* GC guard */ rb_ivar_set(rb_mObjSpace, proc_key, proc); /* GC guard */
rb_tracepoint_enable(tpval); rb_tracepoint_enable(tpval);
} }
return proc; return proc;
} }
static VALUE static VALUE
set_after_gc_start(VALUE rb_mObjSpace, VALUE proc) set_after_gc_start(VALUE rb_mObjSpace, VALUE proc)
{ {
return set_gc_hook(rb_mObjSpace, proc, RUBY_INTERNAL_EVENT_GC_START, return set_gc_hook(rb_mObjSpace, proc, RUBY_INTERNAL_EVENT_GC_START,
"__set_after_gc_start_tpval__", "__set_after_gc_start_proc__"); "__set_after_gc_start_tpval__", "__set_after_gc_start_proc__");
} }
static VALUE static VALUE
set_after_gc_end(VALUE rb_mObjSpace, VALUE proc) set_after_gc_end(VALUE rb_mObjSpace, VALUE proc)
{ {
return set_gc_hook(rb_mObjSpace, proc, RUBY_INTERNAL_EVENT_GC_END, return set_gc_hook(rb_mObjSpace, proc, RUBY_INTERNAL_EVENT_GC_END,
"__set_after_gc_end_tpval__", "__set_after_gc_end_proc__"); "__set_after_gc_end_tpval__", "__set_after_gc_end_proc__");
} }
void void
Init_gc_hook(VALUE rb_mObjSpace) Init_gc_hook(VALUE rb_mObjSpace)
{ {
rb_define_module_function(rb_mObjSpace, "after_gc_start_hook=", set_after_gc_start, 1); rb_define_module_function(rb_mObjSpace, "after_gc_start_hook=", set_after_gc_start, 1);
rb_define_module_function(rb_mObjSpace, "after_gc_end_hook=", set_after_gc_end, 1); rb_define_module_function(rb_mObjSpace, "after_gc_end_hook=", set_after_gc_end, 1);
} }