[前][次][番号順一覧][スレッド一覧]

ruby-changes:25659

From: ko1 <ko1@a...>
Date: Mon, 19 Nov 2012 15:07:20 +0900 (JST)
Subject: [ruby-changes:25659] ko1:r37716 (trunk): * thread.c: add `Thread#backtrace_locations' method.

ko1	2012-11-19 15:07:06 +0900 (Mon, 19 Nov 2012)

  New Revision: 37716

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=37716

  Log:
    * thread.c: add `Thread#backtrace_locations' method.
      This method is similart to `caller_locations' method for
      specific method.
      And fix to accept `level' and `n' parameters for `Thread#backtrace'
      and `Thread#backtrace_locations'.
      `caller' (and `caller_locations') do not return `caller' method
      frame.
      However, `Thread#backtrace' (and `Thread#backtrace_locations')
      return `Thread#backtrace' method frame itself
      if `Thread.current.backtrace' was called.
    * vm_backtrace.c: ditto.
    * internal.h: ditto.
    * test/ruby/test_backtrace.rb: add tests.

  Modified files:
    trunk/ChangeLog
    trunk/NEWS
    trunk/internal.h
    trunk/test/ruby/test_backtrace.rb
    trunk/thread.c
    trunk/vm_backtrace.c

Index: ChangeLog
===================================================================
--- ChangeLog	(revision 37715)
+++ ChangeLog	(revision 37716)
@@ -1,3 +1,22 @@
+Mon Nov 19 14:55:51 2012  Koichi Sasada  <ko1@a...>
+
+	* thread.c: add `Thread#backtrace_locations' method.
+	  This method is similart to `caller_locations' method for
+	  specific method.
+	  And fix to accept `level' and `n' parameters for `Thread#backtrace'
+	  and `Thread#backtrace_locations'.
+	  `caller' (and `caller_locations') do not return `caller' method
+	  frame.
+	  However, `Thread#backtrace' (and `Thread#backtrace_locations')
+	  return `Thread#backtrace' method frame itself
+	  if `Thread.current.backtrace' was called.
+
+	* vm_backtrace.c: ditto.
+
+	* internal.h: ditto.
+
+	* test/ruby/test_backtrace.rb: add tests.
+
 Mon Nov 19 14:54:32 2012  NAKAMURA Usaku  <usa@r...>
 
 	* Makefile.in, common.mk (probes.h): moved to common.mk and changed to
Index: thread.c
===================================================================
--- thread.c	(revision 37715)
+++ thread.c	(revision 37716)
@@ -4623,11 +4623,17 @@
  */
 
 static VALUE
-rb_thread_backtrace_m(VALUE thval)
+rb_thread_backtrace_m(int argc, VALUE *argv, VALUE thval)
 {
-    return rb_thread_backtrace(thval);
+    return vm_thread_backtrace(argc, argv, thval);
 }
 
+static VALUE
+rb_thread_backtrace_locations_m(int argc, VALUE *argv, VALUE thval)
+{
+    return vm_thread_backtrace_locations(argc, argv, thval);
+}
+
 /*
  *  Document-class: ThreadError
  *
@@ -4705,7 +4711,8 @@
     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, "backtrace", rb_thread_backtrace_m, 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);
 
     rb_define_method(rb_cThread, "inspect", rb_thread_inspect, 0);
 
Index: vm_backtrace.c
===================================================================
--- vm_backtrace.c	(revision 37715)
+++ vm_backtrace.c	(revision 37716)
@@ -697,9 +697,44 @@
     return vm_backtrace_str_ary(GET_THREAD(), 0, 0);
 }
 
-VALUE
-rb_thread_backtrace(VALUE thval)
+static VALUE
+vm_backtrace_to_ary(rb_thread_t *th, int argc, VALUE *argv, int lev_deafult, int lev_plus, int to_str)
 {
+    VALUE level, vn;
+    int lev, n;
+
+    rb_scan_args(argc, argv, "02", &level, &vn);
+
+    lev = NIL_P(level) ? lev_deafult : NUM2INT(level);
+
+    if (NIL_P(vn)) {
+	n = 0;
+    }
+    else {
+	n = NUM2INT(vn);
+	if (n == 0) {
+	    return rb_ary_new();
+	}
+    }
+
+    if (lev < 0) {
+	rb_raise(rb_eArgError, "negative level (%d)", lev);
+    }
+    if (n < 0) {
+	rb_raise(rb_eArgError, "negative n (%d)", n);
+    }
+
+    if (to_str) {
+	return vm_backtrace_str_ary(th, lev+lev_plus, n);
+    }
+    else {
+	return vm_backtrace_frame_ary(th, lev+lev_plus, n);
+    }
+}
+
+static VALUE
+thread_backtrace_to_ary(int argc, VALUE *argv, VALUE thval, int to_str)
+{
     rb_thread_t *th;
     GetThreadPtr(thval, th);
 
@@ -713,9 +748,21 @@
 	return Qnil;
     }
 
-    return vm_backtrace_str_ary(th, 0, 0);
+    return vm_backtrace_to_ary(th, argc, argv, 0, 0, to_str);
 }
 
+VALUE
+vm_thread_backtrace(int argc, VALUE *argv, VALUE thval)
+{
+    return thread_backtrace_to_ary(argc, argv, thval, 1);
+}
+
+VALUE
+vm_thread_backtrace_locations(int argc, VALUE *argv, VALUE thval)
+{
+    return thread_backtrace_to_ary(argc, argv, thval, 0);
+}
+
 /*
  *  call-seq:
  *     caller(start=1)    -> array or nil
@@ -749,61 +796,13 @@
 static VALUE
 rb_f_caller(int argc, VALUE *argv)
 {
-    VALUE level, vn;
-    int lev, n;
-
-    rb_scan_args(argc, argv, "02", &level, &vn);
-
-    lev = NIL_P(level) ? 1 : NUM2INT(level);
-
-    if (NIL_P(vn)) {
-	n = 0;
-    }
-    else {
-	n = NUM2INT(vn);
-	if (n == 0) {
-	    return rb_ary_new();
-	}
-    }
-
-    if (lev < 0) {
-	rb_raise(rb_eArgError, "negative level (%d)", lev);
-    }
-    if (n < 0) {
-	rb_raise(rb_eArgError, "negative n (%d)", n);
-    }
-
-    return vm_backtrace_str_ary(GET_THREAD(), lev+1, n);
+    return vm_backtrace_to_ary(GET_THREAD(), argc, argv, 1, 1, 1);
 }
 
 static VALUE
 rb_f_caller_locations(int argc, VALUE *argv)
 {
-    VALUE level, vn;
-    int lev, n;
-
-    rb_scan_args(argc, argv, "02", &level, &vn);
-
-    lev = NIL_P(level) ? 1 : NUM2INT(level);
-
-    if (NIL_P(vn)) {
-	n = 0;
-    }
-    else {
-	n = NUM2INT(vn);
-	if (n == 0) {
-	    return rb_ary_new();
-	}
-    }
-
-    if (lev < 0) {
-	rb_raise(rb_eArgError, "negative level (%d)", lev);
-    }
-    if (n < 0) {
-	rb_raise(rb_eArgError, "negative n (%d)", n);
-    }
-
-    return vm_backtrace_frame_ary(GET_THREAD(), lev+1, n);
+    return vm_backtrace_to_ary(GET_THREAD(), argc, argv, 1, 1, 0);
 }
 
 /* called from Init_vm() in vm.c */
Index: NEWS
===================================================================
--- NEWS	(revision 37715)
+++ NEWS	(revision 37716)
@@ -56,6 +56,8 @@
       * added Kernel#using, which imports refinements into the current scope.
         [experimental]
       * added Kernel#__dir__ which returns a current dirname.
+      * added Kernel#caller_locations which returns an array of
+        frame information objects.
     * extended method:
       * Kernel#warn accepts multiple args in like puts.
       * Kernel#caller accepts second optional argument `n' which specify
@@ -125,6 +127,8 @@
         variable keys.
       * added Thread#thread_variable? for testing to see if a particular thread
         variable has been set.
+      * added Thread#backtrace_locations which returns similar information of
+        Kernel#caller_locations.
 
   * Time
     * change return value:
Index: internal.h
===================================================================
--- internal.h	(revision 37715)
+++ internal.h	(revision 37716)
@@ -310,7 +310,9 @@
 
 /* vm_backtrace.c */
 void Init_vm_backtrace(void);
-VALUE rb_thread_backtrace(VALUE thval);
+VALUE vm_thread_backtrace(int argc, VALUE *argv, VALUE thval);
+VALUE vm_thread_backtrace_locations(int argc, VALUE *argv, VALUE thval);
+
 VALUE rb_make_backtrace(void);
 void rb_backtrace_print_as_bugreport(void);
 int rb_backtrace_p(VALUE obj);
Index: test/ruby/test_backtrace.rb
===================================================================
--- test/ruby/test_backtrace.rb	(revision 37715)
+++ test/ruby/test_backtrace.rb	(revision 37716)
@@ -1,5 +1,5 @@
-
 require 'test/unit'
+require 'thread'
 
 class TestBacktrace < Test::Unit::TestCase
   def test_exception
@@ -91,4 +91,39 @@
     }
     assert_equal(cs, locs)
   end
+
+  def th_rec q, n=10
+    if n > 1
+      th_rec q, n-1
+    else
+      q.pop
+    end
+  end
+
+  def test_thread_backtrace
+    begin
+      q = Queue.new
+      th = Thread.new{
+        th_rec q
+      }
+      sleep 0.5
+      th_backtrace = th.backtrace
+      th_locations = th.backtrace_locations
+
+      assert_equal(10, th_backtrace.count{|e| e =~ /th_rec/})
+      assert_equal(th_backtrace, th_locations.map{|e| e.to_s})
+      assert_equal(th_backtrace, th.backtrace(0))
+      assert_equal(th_locations.map{|e| e.to_s},
+                   th.backtrace_locations(0).map{|e| e.to_s})
+      th_backtrace.size.times{|n|
+        assert_equal(n, th.backtrace(0, n).size)
+        assert_equal(n, th.backtrace_locations(0, n).size)
+      }
+      n = th_backtrace.size
+      assert_equal(n, th.backtrace(0, n + 1).size)
+      assert_equal(n, th.backtrace_locations(0, n + 1).size)
+    ensure
+      q << true
+    end
+  end
 end

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]