diff --git a/gc.c b/gc.c index f91d1e3..ef65c8b 100644 --- a/gc.c +++ b/gc.c @@ -1741,6 +1741,10 @@ newobj_of(VALUE klass, VALUE flags, VALUE v1, VALUE v2, VALUE v3) #endif objspace->total_allocated_objects++; + + rb_thread_t *th = GET_THREAD(); + th->allocated_objects++; + gc_event_hook(objspace, RUBY_INTERNAL_EVENT_NEWOBJ, obj); gc_report(5, objspace, "newobj: %s\n", obj_info(obj)); diff --git a/test/ruby/test_thread.rb b/test/ruby/test_thread.rb index ade680c..f77df5f 100644 --- a/test/ruby/test_thread.rb +++ b/test/ruby/test_thread.rb @@ -1046,4 +1046,17 @@ q.pop t.new {} end end + + def test_thread_allocated_objects + count = 0 + t = Thread.new do + 1000.times do + Object.new + end + count += Thread.current.allocated_objects + end + + t.join + assert_equal 1000, count + end end diff --git a/thread.c b/thread.c index 6cf6d52..44e692f 100644 --- a/thread.c +++ b/thread.c @@ -2568,6 +2568,14 @@ rb_thread_group(VALUE thread) return group; } +VALUE +rb_thread_allocated_objects(VALUE thread) +{ + rb_thread_t *th; + GetThreadPtr(thread, th); + return LONG2NUM(th->allocated_objects); +} + static const char * thread_status_name(rb_thread_t *th) { @@ -5036,6 +5044,7 @@ Init_Thread(void) rb_define_method(rb_cThread, "abort_on_exception=", rb_thread_abort_exc_set, 1); rb_define_method(rb_cThread, "safe_level", rb_thread_safe_level, 0); rb_define_method(rb_cThread, "group", rb_thread_group, 0); + rb_define_method(rb_cThread, "allocated_objects", rb_thread_allocated_objects, 0); rb_define_method(rb_cThread, "backtrace", rb_thread_backtrace_m, -1); rb_define_method(rb_cThread, "backtrace_locations", rb_thread_backtrace_locations_m, -1); diff --git a/vm_core.h b/vm_core.h index 97df64f..f78cc0a 100644 --- a/vm_core.h +++ b/vm_core.h @@ -598,6 +598,7 @@ typedef struct rb_thread_struct { int safe_level; int raised_flag; VALUE last_status; /* $? */ + long allocated_objects; /* passing state */ int state;