[前][次][番号順一覧][スレッド一覧][生データ]

yarv-diff:210

From: ko1 atdot.net
Date: 7 Feb 2006 05:44:52 -0000
Subject: [yarv-diff:210] r368 - in trunk: . benchmark test/ruby yarvtest

Author: ko1
Date: 2006-02-07 14:44:51 +0900 (Tue, 07 Feb 2006)
New Revision: 368

Modified:
   trunk/ChangeLog
   trunk/benchmark/bmx_temp.rb
   trunk/eval.c
   trunk/eval_load.c
   trunk/eval_thread.c
   trunk/gc.c
   trunk/ruby.h
   trunk/signal.c
   trunk/test.rb
   trunk/test/ruby/test_gc.rb
   trunk/thread.c
   trunk/vm.c
   trunk/yarvcore.c
   trunk/yarvcore.h
   trunk/yarvtest/test_thread.rb
Log:
	* eval.c, eval_load.c : remove rb_thread_start_1()

	* eval.c : fix some prototypes and indents

	* eval_thread.c, thread.c : move some functions
	from eval_thread.c to thread.c

	* signal.c (sighandler) : add line braek in error message

	* yarvcore.c, yarvcore.h, thread.c : support ThreadGroup

	* ruby.h, gc.c, vm.c : make new basic type RValue and T_VALUE.
	RValue includes three values in itself.  RValue is used as
	svar



Modified: trunk/ChangeLog
===================================================================
--- trunk/ChangeLog	2006-02-06 14:52:06 UTC (rev 367)
+++ trunk/ChangeLog	2006-02-07 05:44:51 UTC (rev 368)
@@ -4,6 +4,24 @@
 #  from Mon, 03 May 2004 01:24:19 +0900
 #
 
+2006-02-07(Tue) 14:42:25 +0900  Koichi Sasada  <ko1 atdot.net>
+
+	* eval.c, eval_load.c : remove rb_thread_start_1()
+
+	* eval.c : fix some prototypes and indents
+
+	* eval_thread.c, thread.c : move some functions
+	from eval_thread.c to thread.c
+
+	* signal.c (sighandler) : add line braek in error message
+
+	* yarvcore.c, yarvcore.h, thread.c : support ThreadGroup
+
+	* ruby.h, gc.c, vm.c : make new basic type RValue and T_VALUE.
+	RValue includes three values in itself.  RValue is used as
+	svar
+
+
 2006-02-06(Mon) 23:51:41 +0900  Minero Aoki  <aamine loveruby.net>
 
 	* test/ruby/test_hash.rb: import many tests from rubicon.

Modified: trunk/benchmark/bmx_temp.rb
===================================================================
--- trunk/benchmark/bmx_temp.rb	2006-02-06 14:52:06 UTC (rev 367)
+++ trunk/benchmark/bmx_temp.rb	2006-02-07 05:44:51 UTC (rev 368)
@@ -1,4 +1,18 @@
+1000000.times{
+}
+__END__
 
+ths = (1..10).map{
+  Thread.new{
+    1000000.times{
+    }
+  }
+}
+ths.each{|e|
+  e.join
+}
+
+__END__
 $pr = proc{}
 def m
   $pr.call

Modified: trunk/eval.c
===================================================================
--- trunk/eval.c	2006-02-06 14:52:06 UTC (rev 367)
+++ trunk/eval.c	2006-02-07 05:44:51 UTC (rev 368)
@@ -109,7 +109,6 @@
 # endif
 #endif
 
-NORETURN(void rb_thread_start_1(void));
 void Init_yarv(void);
 
 void
@@ -173,9 +172,6 @@
     ruby_process_options(argc, argv);
   }
   else {
-    if (state == TAG_THREAD) {
-      rb_thread_start_1();
-    }
     trace_func = 0;
     tracing = 0;
     exit(error_handle(state));
@@ -239,9 +235,6 @@
     rb_thread_cleanup();
     rb_thread_wait_other_threads();
   }
-  else if (state == TAG_THREAD) {
-    rb_thread_start_1();
-  }
   else if (ex == 0) {
     ex = state;
   }
@@ -510,28 +503,27 @@
 }
 
 int
-rb_remove_event_hook(func)
-    rb_event_hook_func_t func;
+rb_remove_event_hook(rb_event_hook_func_t func)
 {
-    rb_event_hook_t *prev, *hook;
+  rb_event_hook_t *prev, *hook;
 
-    prev = NULL;
-    hook = event_hooks;
-    while (hook) {
-	if (hook->func == func) {
-	    if (prev) {
-		prev->next = hook->next;
-	    }
-	    else {
-		event_hooks = hook->next;
-	    }
-	    xfree(hook);
-	    return 0;
-	}
-	prev = hook;
-	hook = hook->next;
+  prev = NULL;
+  hook = event_hooks;
+  while (hook) {
+    if (hook->func == func) {
+      if (prev) {
+        prev->next = hook->next;
+      }
+      else {
+        event_hooks = hook->next;
+      }
+      xfree(hook);
+      return 0;
     }
-    return -1;
+    prev = hook;
+    hook = hook->next;
+  }
+  return -1;
 }
 
 /*
@@ -1409,9 +1401,6 @@
     if ((status = EXEC_TAG()) == 0) {
 	result = (*proc)(data);
     }
-    else if (status == TAG_THREAD) {
-	rb_thread_start_1();
-    }
     cont_protect = ((NODE *)cont_protect)->u1.value;
     POP_THREAD_TAG();
     if (state) {
@@ -1660,18 +1649,15 @@
 }
 
 VALUE
-rb_apply(recv, mid, args)
-    VALUE recv;
-    ID mid;
-    VALUE args;
+rb_apply(VALUE recv, ID mid, VALUE args)
 {
-    int argc;
-    VALUE *argv;
+  int argc;
+  VALUE *argv;
 
-    argc = RARRAY(args)->len; /* Assigns LONG, but argc is INT */
-    argv = ALLOCA_N(VALUE, argc);
-    MEMCPY(argv, RARRAY(args)->ptr, VALUE, argc);
-    return rb_call(CLASS_OF(recv), recv, mid, argc, argv, NOEX_NOSUPER);
+  argc = RARRAY(args)->len; /* Assigns LONG, but argc is INT */
+  argv = ALLOCA_N(VALUE, argc);
+  MEMCPY(argv, RARRAY(args)->ptr, VALUE, argc);
+  return rb_call(CLASS_OF(recv), recv, mid, argc, argv, NOEX_NOSUPER);
 }
 
 /*
@@ -1791,38 +1777,36 @@
  */
 
 static VALUE
-rb_f_caller(argc, argv)
-    int argc;
-    VALUE *argv;
+rb_f_caller(int argc, VALUE *argv)
 {
-    VALUE level;
-    int lev;
+  VALUE level;
+  int lev;
 
-    rb_scan_args(argc, argv, "01", &level);
+  rb_scan_args(argc, argv, "01", &level);
 
-    if (NIL_P(level)) lev = 1;
-    else lev = NUM2INT(level);
-    if (lev < 0) rb_raise(rb_eArgError, "negative level (%d)", lev);
+  if (NIL_P(level)) lev = 1;
+  else lev = NUM2INT(level);
+  if (lev < 0) rb_raise(rb_eArgError, "negative level (%d)", lev);
 
-    return backtrace(lev);
+  return backtrace(lev);
 }
 
 void
-rb_backtrace()
+rb_backtrace(void)
 {
-    long i;
-    VALUE ary;
+  long i;
+  VALUE ary;
 
-    ary = backtrace(-1);
-    for (i=0; i<RARRAY(ary)->len; i++) {
-	printf("\tfrom %s\n", RSTRING(RARRAY(ary)->ptr[i])->ptr);
-    }
+  ary = backtrace(-1);
+  for (i=0; i<RARRAY(ary)->len; i++) {
+    printf("\tfrom %s\n", RSTRING(RARRAY(ary)->ptr[i])->ptr);
+  }
 }
 
 static VALUE
-make_backtrace()
+make_backtrace(void)
 {
-    return backtrace(-1);
+  return backtrace(-1);
 }
 
 static ID
@@ -1907,7 +1891,6 @@
     file = ruby_sourcefile;
     line = ruby_sourceline;
   }
-
   PUSH_TAG(PROT_NONE);
   if((state = EXEC_TAG()) == 0){
     yarv_iseq_t *iseq;
@@ -2072,6 +2055,7 @@
     }
     pcref = th_cfp_svar(cfp, -1);
     stored_cref = *pcref;
+    /* this cause GC error */
     *pcref = rb_ary_dup(th->cref_stack);
   }
 
@@ -2267,19 +2251,16 @@
  */
 
 static VALUE
-rb_mod_public(argc, argv, module)
-    int argc;
-    VALUE *argv;
-    VALUE module;
+rb_mod_public(int argc, VALUE *argv, VALUE module)
 {
-    secure_visibility(module);
-    if (argc == 0) {
-	SCOPE_SET(NOEX_PUBLIC);
-    }
-    else {
-	set_method_visibility(module, argc, argv, NOEX_PUBLIC);
-    }
-    return module;
+  secure_visibility(module);
+  if (argc == 0) {
+    SCOPE_SET(NOEX_PUBLIC);
+  }
+  else {
+    set_method_visibility(module, argc, argv, NOEX_PUBLIC);
+  }
+  return module;
 }
 
 /*
@@ -2293,19 +2274,16 @@
  */
 
 static VALUE
-rb_mod_protected(argc, argv, module)
-    int argc;
-    VALUE *argv;
-    VALUE module;
+rb_mod_protected(int argc, VALUE *argv, VALUE module)
 {
-    secure_visibility(module);
-    if (argc == 0) {
-	SCOPE_SET(NOEX_PROTECTED);
-    }
-    else {
-	set_method_visibility(module, argc, argv, NOEX_PROTECTED);
-    }
-    return module;
+  secure_visibility(module);
+  if (argc == 0) {
+    SCOPE_SET(NOEX_PROTECTED);
+  }
+  else {
+    set_method_visibility(module, argc, argv, NOEX_PROTECTED);
+  }
+  return module;
 }
 
 /*
@@ -2330,14 +2308,14 @@
 static VALUE
 rb_mod_private(int argc, VALUE *argv, VALUE module)
 {
-    secure_visibility(module);
-    if (argc == 0) {
-	SCOPE_SET(NOEX_PRIVATE);
-    }
-    else {
-	set_method_visibility(module, argc, argv, NOEX_PRIVATE);
-    }
-    return module;
+  secure_visibility(module);
+  if (argc == 0) {
+    SCOPE_SET(NOEX_PRIVATE);
+  }
+  else {
+    set_method_visibility(module, argc, argv, NOEX_PRIVATE);
+  }
+  return module;
 }
 
 /*
@@ -2348,13 +2326,10 @@
  */
 
 static VALUE
-rb_mod_public_method(argc, argv, obj)
-    int argc;
-    VALUE *argv;
-    VALUE obj;
+rb_mod_public_method(int argc, VALUE *argv, VALUE obj)
 {
-    set_method_visibility(CLASS_OF(obj), argc, argv, NOEX_PUBLIC);
-    return obj;
+  set_method_visibility(CLASS_OF(obj), argc, argv, NOEX_PUBLIC);
+  return obj;
 }
 
 /*
@@ -2374,13 +2349,10 @@
  */
 
 static VALUE
-rb_mod_private_method(argc, argv, obj)
-    int argc;
-    VALUE *argv;
-    VALUE obj;
+rb_mod_private_method(int argc, VALUE *argv, VALUE obj)
 {
-    set_method_visibility(CLASS_OF(obj), argc, argv, NOEX_PRIVATE);
-    return obj;
+  set_method_visibility(CLASS_OF(obj), argc, argv, NOEX_PRIVATE);
+  return obj;
 }
 
 /*
@@ -2394,19 +2366,15 @@
  */
 
 static VALUE
-top_public(argc, argv)
-    int argc;
-    VALUE *argv;
+top_public(int argc, VALUE *argv)
 {
-    return rb_mod_public(argc, argv, rb_cObject);
+  return rb_mod_public(argc, argv, rb_cObject);
 }
 
 static VALUE
-top_private(argc, argv)
-    int argc;
-    VALUE *argv;
+top_private(int argc, VALUE *argv)
 {
-    return rb_mod_private(argc, argv, rb_cObject);
+  return rb_mod_private(argc, argv, rb_cObject);
 }
 
 /*
@@ -2500,20 +2468,19 @@
  */
 
 static VALUE
-rb_mod_append_features(module, include)
-    VALUE module, include;
+rb_mod_append_features(VALUE module, VALUE include)
 {
-    switch (TYPE(include)) {
-      case T_CLASS:
-      case T_MODULE:
-	break;
-      default:
-	Check_Type(include, T_CLASS);
-	break;
-    }
-    rb_include_module(include, module);
+  switch (TYPE(include)) {
+  case T_CLASS:
+  case T_MODULE:
+    break;
+  default:
+    Check_Type(include, T_CLASS);
+    break;
+  }
+  rb_include_module(include, module);
 
-    return module;
+  return module;
 }
 
 /*
@@ -2524,19 +2491,16 @@
  */
 
 static VALUE
-rb_mod_include(argc, argv, module)
-    int argc;
-    VALUE *argv;
-    VALUE module;
+rb_mod_include(int argc, VALUE *argv, VALUE module)
 {
-    int i;
+  int i;
 
-    for (i=0; i<argc; i++) Check_Type(argv[i], T_MODULE);
-    while (argc--) {
-	rb_funcall(argv[argc], rb_intern("append_features"), 1, module);
-	rb_funcall(argv[argc], rb_intern("included"), 1, module);
-    }
-    return module;
+  for (i=0; i<argc; i++) Check_Type(argv[i], T_MODULE);
+  while (argc--) {
+    rb_funcall(argv[argc], rb_intern("append_features"), 1, module);
+    rb_funcall(argv[argc], rb_intern("included"), 1, module);
+  }
+  return module;
 }
 
 void
@@ -2547,10 +2511,9 @@
 }
 
 void
-rb_extend_object(obj, module)
-    VALUE obj, module;
+rb_extend_object(VALUE obj, VALUE module)
 {
-    rb_include_module(rb_singleton_class(obj), module);
+  rb_include_module(rb_singleton_class(obj), module);
 }
 
 /*
@@ -2581,11 +2544,10 @@
  */
 
 static VALUE
-rb_mod_extend_object(mod, obj)
-    VALUE mod, obj;
+rb_mod_extend_object(VALUE mod, VALUE obj)
 {
-    rb_extend_object(obj, mod);
-    return obj;
+  rb_extend_object(obj, mod);
+  return obj;
 }
 
 /*
@@ -2614,22 +2576,19 @@
  */
 
 static VALUE
-rb_obj_extend(argc, argv, obj)
-    int argc;
-    VALUE *argv;
-    VALUE obj;
+rb_obj_extend(int argc, VALUE *argv, VALUE obj)
 {
-    int i;
+  int i;
 
-    if (argc == 0) {
-	rb_raise(rb_eArgError, "wrong number of arguments (0 for 1)");
-    }
-    for (i=0; i<argc; i++) Check_Type(argv[i], T_MODULE);
-    while (argc--) {
-	rb_funcall(argv[argc], rb_intern("extend_object"), 1, obj);
-	rb_funcall(argv[argc], rb_intern("extended"), 1, obj);
-    }
-    return obj;
+  if (argc == 0) {
+    rb_raise(rb_eArgError, "wrong number of arguments (0 for 1)");
+  }
+  for (i=0; i<argc; i++) Check_Type(argv[i], T_MODULE);
+  while (argc--) {
+    rb_funcall(argv[argc], rb_intern("extend_object"), 1, obj);
+    rb_funcall(argv[argc], rb_intern("extended"), 1, obj);
+  }
+  return obj;
 }
 
 /*
@@ -2642,17 +2601,14 @@
  */
 
 static VALUE
-top_include(argc, argv, self)
-    int argc;
-    VALUE *argv;
-    VALUE self;
+top_include(int argc, VALUE *argv, VALUE self)
 {
-    rb_secure(4);
-    if (ruby_wrapper) {
-	rb_warning("main#include in the wrapped load is effective only in wrapper module");
-	return rb_mod_include(argc, argv, ruby_wrapper);
-    }
-    return rb_mod_include(argc, argv, rb_cObject);
+  rb_secure(4);
+  if (ruby_wrapper) {
+    rb_warning("main#include in the wrapped load is effective only in wrapper module");
+    return rb_mod_include(argc, argv, ruby_wrapper);
+  }
+  return rb_mod_include(argc, argv, rb_cObject);
 }
 
 VALUE rb_f_trace_var();
@@ -2732,7 +2688,7 @@
 th_collect_local_variables_in_heap(yarv_thread_t *th, VALUE *dfp, VALUE ary);
 
 static VALUE
-rb_f_local_variables()
+rb_f_local_variables(void)
 {
   VALUE ary = rb_ary_new();
   yarv_thread_t *th = GET_THREAD();
@@ -2774,90 +2730,90 @@
 void
 Init_eval()
 {
-    init = rb_intern("initialize");
-    eqq = rb_intern("===");
-    each = rb_intern("each");
+  init = rb_intern("initialize");
+  eqq = rb_intern("===");
+  each = rb_intern("each");
 
-    aref = rb_intern("[]");
-    aset = rb_intern("[]=");
-    match = rb_intern("=~");
-    missing = rb_intern("method_missing");
-    added = rb_intern("method_added");
-    singleton_added = rb_intern("singleton_method_added");
-    removed = rb_intern("method_removed");
-    singleton_removed = rb_intern("singleton_method_removed");
-    undefined = rb_intern("method_undefined");
-    singleton_undefined = rb_intern("singleton_method_undefined");
+  aref = rb_intern("[]");
+  aset = rb_intern("[]=");
+  match = rb_intern("=~");
+  missing = rb_intern("method_missing");
+  added = rb_intern("method_added");
+  singleton_added = rb_intern("singleton_method_added");
+  removed = rb_intern("method_removed");
+  singleton_removed = rb_intern("singleton_method_removed");
+  undefined = rb_intern("method_undefined");
+  singleton_undefined = rb_intern("singleton_method_undefined");
 
-    __id__ = rb_intern("__id__");
-    __send__ = rb_intern("__send__");
+  __id__ = rb_intern("__id__");
+  __send__ = rb_intern("__send__");
 
-    rb_global_variable((VALUE*)&ruby_eval_tree);
+  rb_global_variable((VALUE*)&ruby_eval_tree);
 
-    rb_define_virtual_variable("$@", errat_getter, errat_setter);
-    rb_define_virtual_variable("$!", errinfo_getter, errinfo_setter);
+  rb_define_virtual_variable("$@", errat_getter, errat_setter);
+  rb_define_virtual_variable("$!", errinfo_getter, errinfo_setter);
 
-    rb_define_global_function("eval", rb_f_eval, -1);
-    rb_define_global_function("iterator?", rb_f_block_given_p, 0);
-    rb_define_global_function("block_given?", rb_f_block_given_p, 0);
-    rb_define_global_function("method_missing", rb_method_missing, -1);
-    rb_define_global_function("loop", rb_f_loop, 0);
+  rb_define_global_function("eval", rb_f_eval, -1);
+  rb_define_global_function("iterator?", rb_f_block_given_p, 0);
+  rb_define_global_function("block_given?", rb_f_block_given_p, 0);
+  rb_define_global_function("method_missing", rb_method_missing, -1);
+  rb_define_global_function("loop", rb_f_loop, 0);
 
-    rb_define_method(rb_mKernel, "respond_to?", obj_respond_to, -1);
-    respond_to   = rb_intern("respond_to?");
-    basic_respond_to = rb_method_node(rb_cObject, respond_to);
-    rb_global_variable((VALUE*)&basic_respond_to);
-    
-    rb_define_global_function("raise", rb_f_raise, -1);
-    rb_define_global_function("fail", rb_f_raise, -1);
+  rb_define_method(rb_mKernel, "respond_to?", obj_respond_to, -1);
+  respond_to   = rb_intern("respond_to?");
+  basic_respond_to = rb_method_node(rb_cObject, respond_to);
+  rb_global_variable((VALUE*)&basic_respond_to);
 
-    rb_define_global_function("caller", rb_f_caller, -1);
+  rb_define_global_function("raise", rb_f_raise, -1);
+  rb_define_global_function("fail", rb_f_raise, -1);
 
-    rb_define_global_function("global_variables", rb_f_global_variables, 0); /* in variable.c */
-    rb_define_global_function("local_variables", rb_f_local_variables, 0);
+  rb_define_global_function("caller", rb_f_caller, -1);
 
-    rb_define_method(rb_mKernel, "send", rb_f_send, -1);
-    rb_define_method(rb_mKernel, "__send__", rb_f_send, -1);
-    rb_define_method(rb_mKernel, "instance_eval", rb_obj_instance_eval, -1);
+  rb_define_global_function("global_variables", rb_f_global_variables, 0); /* in variable.c */
+  rb_define_global_function("local_variables", rb_f_local_variables, 0);
 
-    rb_define_private_method(rb_cModule, "append_features", rb_mod_append_features, 1);
-    rb_define_private_method(rb_cModule, "extend_object", rb_mod_extend_object, 1);
-    rb_define_private_method(rb_cModule, "include", rb_mod_include, -1);
-    rb_define_private_method(rb_cModule, "public", rb_mod_public, -1);
-    rb_define_private_method(rb_cModule, "protected", rb_mod_protected, -1);
-    rb_define_private_method(rb_cModule, "private", rb_mod_private, -1);
-    rb_define_private_method(rb_cModule, "module_function", rb_mod_modfunc, -1);
-    rb_define_method(rb_cModule, "method_defined?", rb_mod_method_defined, 1);
-    rb_define_method(rb_cModule, "public_method_defined?", rb_mod_public_method_defined, 1);
-    rb_define_method(rb_cModule, "private_method_defined?", rb_mod_private_method_defined, 1);
-    rb_define_method(rb_cModule, "protected_method_defined?", rb_mod_protected_method_defined, 1);
-    rb_define_method(rb_cModule, "public_class_method", rb_mod_public_method, -1);
-    rb_define_method(rb_cModule, "private_class_method", rb_mod_private_method, -1);
-    rb_define_method(rb_cModule, "module_eval", rb_mod_module_eval, -1);
-    rb_define_method(rb_cModule, "class_eval", rb_mod_module_eval, -1);
+  rb_define_method(rb_mKernel, "send", rb_f_send, -1);
+  rb_define_method(rb_mKernel, "__send__", rb_f_send, -1);
+  rb_define_method(rb_mKernel, "instance_eval", rb_obj_instance_eval, -1);
 
-    rb_undef_method(rb_cClass, "module_function");
+  rb_define_private_method(rb_cModule, "append_features", rb_mod_append_features, 1);
+  rb_define_private_method(rb_cModule, "extend_object", rb_mod_extend_object, 1);
+  rb_define_private_method(rb_cModule, "include", rb_mod_include, -1);
+  rb_define_private_method(rb_cModule, "public", rb_mod_public, -1);
+  rb_define_private_method(rb_cModule, "protected", rb_mod_protected, -1);
+  rb_define_private_method(rb_cModule, "private", rb_mod_private, -1);
+  rb_define_private_method(rb_cModule, "module_function", rb_mod_modfunc, -1);
+  rb_define_method(rb_cModule, "method_defined?", rb_mod_method_defined, 1);
+  rb_define_method(rb_cModule, "public_method_defined?", rb_mod_public_method_defined, 1);
+  rb_define_method(rb_cModule, "private_method_defined?", rb_mod_private_method_defined, 1);
+  rb_define_method(rb_cModule, "protected_method_defined?", rb_mod_protected_method_defined, 1);
+  rb_define_method(rb_cModule, "public_class_method", rb_mod_public_method, -1);
+  rb_define_method(rb_cModule, "private_class_method", rb_mod_private_method, -1);
+  rb_define_method(rb_cModule, "module_eval", rb_mod_module_eval, -1);
+  rb_define_method(rb_cModule, "class_eval", rb_mod_module_eval, -1);
 
-    rb_define_private_method(rb_cModule, "remove_method", rb_mod_remove_method, -1);
-    rb_define_private_method(rb_cModule, "undef_method", rb_mod_undef_method, -1);
-    rb_define_private_method(rb_cModule, "alias_method", rb_mod_alias_method, 2);
+  rb_undef_method(rb_cClass, "module_function");
 
-    rb_define_singleton_method(rb_cModule, "nesting", rb_mod_nesting, 0);
-    rb_define_singleton_method(rb_cModule, "constants", rb_mod_s_constants, 0);
+  rb_define_private_method(rb_cModule, "remove_method", rb_mod_remove_method, -1);
+  rb_define_private_method(rb_cModule, "undef_method", rb_mod_undef_method, -1);
+  rb_define_private_method(rb_cModule, "alias_method", rb_mod_alias_method, 2);
 
-    rb_define_singleton_method(ruby_top_self, "include", top_include, -1);
-    rb_define_singleton_method(ruby_top_self, "public", top_public, -1);
-    rb_define_singleton_method(ruby_top_self, "private", top_private, -1);
+  rb_define_singleton_method(rb_cModule, "nesting", rb_mod_nesting, 0);
+  rb_define_singleton_method(rb_cModule, "constants", rb_mod_s_constants, 0);
 
-    rb_define_method(rb_mKernel, "extend", rb_obj_extend, -1);
+  rb_define_singleton_method(ruby_top_self, "include", top_include, -1);
+  rb_define_singleton_method(ruby_top_self, "public", top_public, -1);
+  rb_define_singleton_method(ruby_top_self, "private", top_private, -1);
 
-    rb_define_global_function("trace_var", rb_f_trace_var, -1); /* in variable.c */
-    rb_define_global_function("untrace_var", rb_f_untrace_var, -1); /* in variable.c */
+  rb_define_method(rb_mKernel, "extend", rb_obj_extend, -1);
 
-    rb_define_global_function("set_trace_func", set_trace_func, 1);
-    rb_global_variable(&trace_func);
+  rb_define_global_function("trace_var", rb_f_trace_var, -1); /* in variable.c */
+  rb_define_global_function("untrace_var", rb_f_untrace_var, -1); /* in variable.c */
 
-    rb_define_virtual_variable("$SAFE", safe_getter, safe_setter);
+  rb_define_global_function("set_trace_func", set_trace_func, 1);
+  rb_global_variable(&trace_func);
+
+  rb_define_virtual_variable("$SAFE", safe_getter, safe_setter);
 }
 
 

Modified: trunk/eval_load.c
===================================================================
--- trunk/eval_load.c	2006-02-06 14:52:06 UTC (rev 367)
+++ trunk/eval_load.c	2006-02-07 05:44:51 UTC (rev 368)
@@ -179,9 +179,6 @@
   if ((status = EXEC_TAG()) == 0) {
     rb_load(fname, wrap);
   }
-  else if (status == TAG_THREAD) {
-    rb_thread_start_1();
-  }
   POP_THREAD_TAG();
   if (state) *state = status;
 }

Modified: trunk/eval_thread.c
===================================================================
--- trunk/eval_thread.c	2006-02-06 14:52:06 UTC (rev 367)
+++ trunk/eval_thread.c	2006-02-07 05:44:51 UTC (rev 368)
@@ -807,145 +807,6 @@
 }
 
 
-/*
- *  call-seq:
- *     thr.safe_level   => integer
- *  
- *  Returns the safe level in effect for <i>thr</i>. Setting thread-local safe
- *  levels can help when implementing sandboxes which run insecure code.
- *     
- *     thr = Thread.new { $SAFE = 3; sleep }
- *     Thread.current.safe_level   #=> 0
- *     thr.safe_level              #=> 3
- */
-
-static VALUE
-rb_thread_safe_level(thread)
-    VALUE thread;
-{
-    rb_thread_t th;
-
-    th = rb_thread_check(thread);
-    if (th == curr_thread) {
-	return INT2NUM(ruby_safe_level);
-    }
-    return INT2NUM(th->safe);
-}
-
-static int ruby_thread_abort;
-static VALUE thgroup_default;
-
-
-/*
- *  call-seq:
- *     Thread.abort_on_exception   => true or false
- *  
- *  Returns the status of the global ``abort on exception'' condition.  The
- *  default is <code>false</code>. When set to <code>true</code>, or if the
- *  global <code>$DEBUG</code> flag is <code>true</code> (perhaps because the
- *  command line option <code>-d</code> was specified) all threads will abort
- *  (the process will <code>exit(0)</code>) if an exception is raised in any
- *  thread. See also <code>Thread::abort_on_exception=</code>.
- */
-
-static VALUE
-rb_thread_s_abort_exc()
-{
-    return ruby_thread_abort?Qtrue:Qfalse;
-}
-
-
-/*
- *  call-seq:
- *     Thread.abort_on_exception= boolean   => true or false
- *  
- *  When set to <code>true</code>, all threads will abort if an exception is
- *  raised. Returns the new state.
- *     
- *     Thread.abort_on_exception = true
- *     t1 = Thread.new do
- *       puts  "In new thread"
- *       raise "Exception from thread"
- *     end
- *     sleep(1)
- *     puts "not reached"
- *     
- *  <em>produces:</em>
- *     
- *     In new thread
- *     prog.rb:4: Exception from thread (RuntimeError)
- *     	from prog.rb:2:in `initialize'
- *     	from prog.rb:2:in `new'
- *     	from prog.rb:2
- */
-
-static VALUE
-rb_thread_s_abort_exc_set(self, val)
-    VALUE self, val;
-{
-    rb_secure(4);
-    ruby_thread_abort = RTEST(val);
-    return val;
-}
-
-
-/*
- *  call-seq:
- *     thr.abort_on_exception   => true or false
- *  
- *  Returns the status of the thread-local ``abort on exception'' condition for
- *  <i>thr</i>. The default is <code>false</code>. See also
- *  <code>Thread::abort_on_exception=</code>.
- */
-
-static VALUE
-rb_thread_abort_exc(thread)
-    VALUE thread;
-{
-    return rb_thread_check(thread)->abort?Qtrue:Qfalse;
-}
-
-
-/*
- *  call-seq:
- *     thr.abort_on_exception= boolean   => true or false
- *  
- *  When set to <code>true</code>, causes all threads (including the main
- *  program) to abort if an exception is raised in <i>thr</i>. The process will
- *  effectively <code>exit(0)</code>.
- */
-
-static VALUE
-rb_thread_abort_exc_set(thread, val)
-    VALUE thread, val;
-{
-    rb_secure(4);
-    rb_thread_check(thread)->abort = RTEST(val);
-    return val;
-}
-
-
-/*
- *  call-seq:
- *     thr.group   => thgrp or nil
- *  
- *  Returns the <code>ThreadGroup</code> which contains <i>thr</i>, or nil if
- *  the thread is not a member of any group.
- *     
- *     Thread.main.group   #=> #<ThreadGroup:0x4029d914>
- */
-
-VALUE
-rb_thread_group(thread)
-    VALUE thread;
-{
-    VALUE group = rb_thread_check(thread)->thgroup;
-    if (!group) {
-	group = Qnil;
-    }
-    return group;
-}
-
 #ifdef __ia64__
 # define IA64_INIT(x) x
 #else
@@ -1065,24 +926,6 @@
 int rb_thread_tick = THREAD_TICK;
 #endif
 
-NORETURN(static void rb_thread_terminated _((rb_thread_t, int, enum yarv_thread_status)));
-static VALUE rb_thread_yield _((VALUE, rb_thread_t));
-
-static void
-thread_insert(th)
-    rb_thread_t th;
-{
-    if (!th->next) {
-	/* merge in thread list */
-	th->prev = curr_thread;
-	curr_thread->next->prev = th;
-	th->next = curr_thread->next;
-	curr_thread->next = th;
-	th->priority = curr_thread->priority;
-	th->thgroup = curr_thread->thgroup;
-    }
-}
-
 static VALUE
 rb_thread_start_0(fn, arg, th)
     VALUE (*fn)();
@@ -1093,75 +936,13 @@
   return 0;			/* not reached */
 }
 
-static void
-rb_thread_terminated(th, state, status)
-    rb_thread_t th;
-    int state;
-    enum yarv_thread_status status;
-{
-    if (state && status != THREAD_TO_KILL && !NIL_P(GET_THREAD()->errinfo)) {
-	th->flags |= THREAD_RAISED;
-	if (state == TAG_FATAL) {
-	    /* fatal error within this thread, need to stop whole script */
-	    main_thread->errinfo = GET_THREAD()->errinfo;
-	    rb_thread_cleanup();
-	}
-	else if (rb_obj_is_kind_of(GET_THREAD()->errinfo, rb_eSystemExit)) {
-	    if (th->safe >= 4) {
-		char buf[32];
-
-		sprintf(buf, "Insecure exit at level %d", th->safe);
-		th->errinfo = rb_exc_new2(rb_eSecurityError, buf);
-	    }
-	    else {
-		/* delegate exception to main_thread */
-		rb_thread_main_jump(GET_THREAD()->errinfo, RESTORE_RAISE);
-	    }
-	}
-	else if (th->safe < 4 && (ruby_thread_abort || th->abort || RTEST(ruby_debug))) {
-	    /* exit on main_thread */
-	    rb_thread_main_jump(GET_THREAD()->errinfo, RESTORE_EXIT);
-	}
-	else {
-	    th->errinfo = GET_THREAD()->errinfo;
-	}
-    }
-    rb_thread_schedule();
-    ruby_stop(0);		/* last thread termination */
-}
-
-static VALUE
-rb_thread_yield_0(arg)
-    VALUE arg;
-{
-    return rb_thread_yield(arg, curr_thread);
-}
-
-void
-rb_thread_start_1()
-{
-  // TODO
-  rb_bug("unsupported: rb_thread_start_1");
-}
-
 VALUE
-rb_thread_create(fn, arg)
-    VALUE (*fn)();
-    void *arg;
+rb_thread_create(VALUE (*fn)(), void *arg)
 {
-    Init_stack((VALUE*)&arg);
-    return rb_thread_start_0(fn, arg, rb_thread_alloc(rb_cThread));
+  Init_stack((VALUE*)&arg);
+  return rb_thread_start_0(fn, arg, rb_thread_alloc(rb_cThread));
 }
 
-static VALUE
-rb_thread_yield(arg, th)
-    VALUE arg;
-    rb_thread_t th;
-{
-    const ID *tbl;
-  UNSUPPORTED(rb_thread_yield);
-}
-
 /*
  *  call-seq:
  *     Thread.new([arg]*) {|args| block }   => thread
@@ -1219,24 +1000,10 @@
  */
 
 static VALUE
-rb_thread_initialize(thread, args)
-    VALUE thread, args;
+rb_thread_initialize(VALUE thread, VALUE args)
 {
-    rb_thread_t th;
-
-    if (!rb_block_given_p()) {
-	rb_raise(rb_eThreadError, "must be called with a block");
-    }
-    th = rb_thread_check(thread);
-    if (th->stk_max) {
-	NODE *node = th->node;
-	if (!node) {
-	    rb_raise(rb_eThreadError, "already initialized thread");
-	}
-	rb_raise(rb_eThreadError, "already initialized thread - %s:%d",
-		 node->nd_file, nd_line(node));
-    }
-    return rb_thread_start_0(rb_thread_yield, args, th);
+  // TODO
+  return Qnil;
 }
 
 
@@ -1251,13 +1018,10 @@
  */
 
 static VALUE
-rb_thread_start(klass, args)
-    VALUE klass, args;
+rb_thread_start(VALUE klass, VALUE args)
 {
-    if (!rb_block_given_p()) {
-	rb_raise(rb_eThreadError, "must be called with a block");
-    }
-    return rb_thread_start_0(rb_thread_yield, args, rb_thread_alloc(klass));
+  // TODO
+  return Qnil;
 }
 
 
@@ -1432,186 +1196,7 @@
   UNSUPPORTED(rb_cont_call);
 }
 
-struct thgroup {
-    int enclosed;
-    VALUE group;
-};
 
-
-/*
- * Document-class: ThreadGroup
- *
- *  <code>ThreadGroup</code> provides a means of keeping track of a number of
- *  threads as a group. A <code>Thread</code> can belong to only one
- *  <code>ThreadGroup</code> at a time; adding a thread to a new group will
- *  remove it from any previous group.
- *     
- *  Newly created threads belong to the same group as the thread from which they
- *  were created.
- */
-
-static VALUE thgroup_s_alloc _((VALUE));
-static VALUE
-thgroup_s_alloc(klass)
-    VALUE klass;
-{
-    VALUE group;
-    struct thgroup *data;
-
-    group = Data_Make_Struct(klass, struct thgroup, 0, free, data);
-    data->enclosed = 0;
-    data->group = group;
-
-    return group;
-}
-
-
-/*
- *  call-seq:
- *     thgrp.list   => array
- *  
- *  Returns an array of all existing <code>Thread</code> objects that belong to
- *  this group.
- *     
- *     ThreadGroup::Default.list   #=> [#<Thread:0x401bdf4c run>]
- */
-
-static VALUE
-thgroup_list(group)
-    VALUE group;
-{
-    struct thgroup *data;
-    rb_thread_t th;
-    VALUE ary;
-
-    Data_Get_Struct(group, struct thgroup, data);
-    ary = rb_ary_new();
-
-    FOREACH_THREAD(th) {
-	if (th->thgroup == data->group) {
-	    rb_ary_push(ary, th->thread);
-	}
-    }
-    END_FOREACH(th);
-
-    return ary;
-}
-
-
-/*
- *  call-seq:
- *     thgrp.enclose   => thgrp
- *  
- *  Prevents threads from being added to or removed from the receiving
- *  <code>ThreadGroup</code>. New threads can still be started in an enclosed
- *  <code>ThreadGroup</code>.
- *     
- *     ThreadGroup::Default.enclose        #=> #<ThreadGroup:0x4029d914>
- *     thr = Thread::new { Thread.stop }   #=> #<Thread:0x402a7210 sleep>
- *     tg = ThreadGroup::new               #=> #<ThreadGroup:0x402752d4>
- *     tg.add thr
- *
- *  <em>produces:</em>
- *
- *     ThreadError: can't move from the enclosed thread group
- */
-
-VALUE
-thgroup_enclose(group)
-    VALUE group;
-{
-    struct thgroup *data;
-
-    Data_Get_Struct(group, struct thgroup, data);
-    data->enclosed = 1;
-
-    return group;
-}
-
-
-/*
- *  call-seq:
- *     thgrp.enclosed?   => true or false
- *  
- *  Returns <code>true</code> if <em>thgrp</em> is enclosed. See also
- *  ThreadGroup#enclose.
- */
-
-static VALUE
-thgroup_enclosed_p(group)
-    VALUE group;
-{
-    struct thgroup *data;
-
-    Data_Get_Struct(group, struct thgroup, data);
-    if (data->enclosed) return Qtrue;
-    return Qfalse;
-}
-
-
-/*
- *  call-seq:
- *     thgrp.add(thread)   => thgrp
- *  
- *  Adds the given <em>thread</em> to this group, removing it from any other
- *  group to which it may have previously belonged.
- *     
- *     puts "Initial group is #{ThreadGroup::Default.list}"
- *     tg = ThreadGroup.new
- *     t1 = Thread.new { sleep }
- *     t2 = Thread.new { sleep }
- *     puts "t1 is #{t1}"
- *     puts "t2 is #{t2}"
- *     tg.add(t1)
- *     puts "Initial group now #{ThreadGroup::Default.list}"
- *     puts "tg group now #{tg.list}"
- *     
- *  <em>produces:</em>
- *     
- *     Initial group is #<Thread:0x401bdf4c>
- *     t1 is #<Thread:0x401b3c90>
- *     t2 is #<Thread:0x401b3c18>
- *     Initial group now #<Thread:0x401b3c18>#<Thread:0x401bdf4c>
- *     tg group now #<Thread:0x401b3c90>
- */
-
-static VALUE
-thgroup_add(group, thread)
-    VALUE group, thread;
-{
-    rb_thread_t th;
-    struct thgroup *data;
-
-    rb_secure(4);
-    th = rb_thread_check(thread);
-    if (!th->next || !th->prev) {
-	rb_raise(rb_eTypeError, "wrong argument type %s (expected Thread)",
-		 rb_obj_classname(thread));
-    }
-
-    if (OBJ_FROZEN(group)) {
-      rb_raise(rb_eThreadError, "can't move to the frozen thread group");
-    }
-    Data_Get_Struct(group, struct thgroup, data);
-    if (data->enclosed) {
-	rb_raise(rb_eThreadError, "can't move to the enclosed thread group");
-    }
-
-    if (!th->thgroup) {
-	return Qnil;
-    }
-    if (OBJ_FROZEN(th->thgroup)) {
-	rb_raise(rb_eThreadError, "can't move from the frozen thread group");
-    }
-    Data_Get_Struct(th->thgroup, struct thgroup, data);
-    if (data->enclosed) {
-	rb_raise(rb_eThreadError, "can't move from the enclosed thread group");
-    }
-
-    th->thgroup = group;
-    return group;
-}
-
 /* variables for recursive traversals */
 static ID recursive_key;
 
@@ -1643,12 +1228,6 @@
     rb_define_singleton_method(rb_cThread, "abort_on_exception", rb_thread_s_abort_exc, 0);
     rb_define_singleton_method(rb_cThread, "abort_on_exception=", rb_thread_s_abort_exc_set, 1);
 
-    rb_define_method(rb_cThread, "abort_on_exception", rb_thread_abort_exc, 0);
-    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_cCont = rb_define_class("Continuation", rb_cObject);
     rb_undef_alloc_func(rb_cCont);
     rb_undef_method(CLASS_OF(rb_cCont), "new");
@@ -1656,16 +1235,6 @@
     rb_define_method(rb_cCont, "[]", rb_cont_call, -1);
     rb_define_global_function("callcc", rb_callcc, 0);
 
-    cThGroup = rb_define_class("ThreadGroup", rb_cObject);
-    rb_define_alloc_func(cThGroup, thgroup_s_alloc);
-    rb_define_method(cThGroup, "list", thgroup_list, 0);
-    rb_define_method(cThGroup, "enclose", thgroup_enclose, 0);
-    rb_define_method(cThGroup, "enclosed?", thgroup_enclosed_p, 0);
-    rb_define_method(cThGroup, "add", thgroup_add, 1);
-    thgroup_default = rb_obj_alloc(cThGroup);
-    rb_define_const(cThGroup, "Default", thgroup_default);
-    rb_global_variable(&thgroup_default);
-
    */
 }
 

Modified: trunk/gc.c
===================================================================
--- trunk/gc.c	2006-02-06 14:52:06 UTC (rev 367)
+++ trunk/gc.c	2006-02-07 05:44:51 UTC (rev 368)
@@ -109,6 +109,11 @@
 static int gc_debug_flag = 0;
 
 static VALUE
+get_gc_debug_flag(VALUE self){
+  return gc_debug_flag ? Qtrue : Qfalse;
+}
+
+static VALUE
 set_gc_debug_flag(VALUE self, VALUE v){
   gc_debug_flag = (v == Qtrue);
   return v;
@@ -971,6 +976,14 @@
 	}
 	break;
 
+      case T_VALUE:
+	{
+            rb_gc_mark(RVALUE(obj)->v1);
+            rb_gc_mark(RVALUE(obj)->v2);
+            ptr = RVALUE(obj)->v3;
+	}
+	break;
+
       default:
 	rb_bug("rb_gc_mark(): unknown data type 0x%lx(%p) %s",
 	       obj->as.basic.flags & T_MASK, obj,
@@ -1181,6 +1194,7 @@
       case T_FLOAT:
       case T_VARMAP:
       case T_BLOCK:
+      case T_VALUE:
 	break;
 
       case T_BIGNUM:
@@ -1216,7 +1230,6 @@
 	if (RANY(obj)->as.rstruct.ptr) {
 	    RUBY_CRITICAL(free(RANY(obj)->as.rstruct.ptr));
 	}
-	break;
 
       default:
 	rb_bug("gc_sweep(): unknown data type 0x%lx(%p)", 
@@ -1885,6 +1898,7 @@
     rb_define_singleton_method(rb_mGC, "start", rb_gc_start, 0);
     rb_define_singleton_method(rb_mGC, "enable", rb_gc_enable, 0);
     rb_define_singleton_method(rb_mGC, "disable", rb_gc_disable, 0);
+    rb_define_singleton_method(rb_mGC, "debug_flag", get_gc_debug_flag, 0);
     rb_define_singleton_method(rb_mGC, "debug_flag=", set_gc_debug_flag, 1);
     rb_define_method(rb_mGC, "garbage_collect", rb_gc_start, 0);
 

Modified: trunk/ruby.h
===================================================================
--- trunk/ruby.h	2006-02-06 14:52:06 UTC (rev 367)
+++ trunk/ruby.h	2006-02-07 05:44:51 UTC (rev 368)
@@ -220,6 +220,7 @@
 #define T_MATCH  0x13
 #define T_SYMBOL 0x14
 
+#define T_VALUE  0x1a
 #define T_BLOCK  0x1b
 #define T_UNDEF  0x1c
 #define T_VARMAP 0x1d
@@ -334,6 +335,13 @@
     struct st_table *iv_tbl;
 };
 
+struct RValue {
+    struct RBasic basic;
+    VALUE v1;
+    VALUE v2;
+    VALUE v3;
+};
+
 struct RClass {
     struct RBasic basic;
     struct st_table *iv_tbl;
@@ -444,6 +452,7 @@
 #define RSTRUCT(obj) (R_CAST(RStruct)(obj))
 #define RBIGNUM(obj) (R_CAST(RBignum)(obj))
 #define RFILE(obj)   (R_CAST(RFile)(obj))
+#define RVALUE(obj)  (R_CAST(RValue)(obj))
 
 #define FL_SINGLETON FL_USER0
 #define FL_MARK      (1<<5)

Modified: trunk/signal.c
===================================================================
--- trunk/signal.c	2006-02-06 14:52:06 UTC (rev 367)
+++ trunk/signal.c	2006-02-07 05:44:51 UTC (rev 368)
@@ -419,7 +419,7 @@
   
   if(next_head == th->signal_queue.tail){
     /* signal queue overflow */
-    fprintf(stderr, "Signal Queue overflow. This signal (%d) is ignored.", sig);
+    fprintf(stderr, "Signal Queue overflow. This signal (%d) is ignored.\n", sig);
   }
   else{
     th->signal_queue.buff[th->signal_queue.head] = sig;

Modified: trunk/test/ruby/test_gc.rb
===================================================================
--- trunk/test/ruby/test_gc.rb	2006-02-06 14:52:06 UTC (rev 367)
+++ trunk/test/ruby/test_gc.rb	2006-02-07 05:44:51 UTC (rev 368)
@@ -8,7 +8,8 @@
   end
 
   def test_gc
-    # GC.debug_flag = false
+    prev_df = GC.debug_flag
+    GC.debug_flag = false
     
     assert_nothing_raised do
       1.upto(10000) {
@@ -29,6 +30,6 @@
     GC.start
     assert true   # reach here or dumps core
 
-    # GC.debug_flag = true
+    GC.debug_flag = prev_df
   end
 end

Modified: trunk/test.rb
===================================================================
--- trunk/test.rb	2006-02-06 14:52:06 UTC (rev 367)
+++ trunk/test.rb	2006-02-07 05:44:51 UTC (rev 368)
@@ -1,4 +1,118 @@
+
+      /a(b)(c)d/ =~ 'xyzabcdefgabcdefg'
+      [$1, $2, $3, $~.class, $&, $`, $', $+]
+
+
+__END__
+
+class C
+end
+
+C.module_eval %q{
+  def m
+  end
+}
+
+__END__
+
+require 'fileutils'
+
+__END__
+
+thg = ThreadGroup.new
+
 t = Thread.new{
+  thg.add Thread.current
+  sleep
+}
+sleep 0.1
+[thg.list.size, ThreadGroup::Default.size]
+
+__END__
+a = b = nil
+  if a and b
+    p :ng
+  end
+  p :ok
+__END__
+  a = nil
+  if !a
+    p :ok
+  end
+__END__
+
+if 1
+    p :ok
+  end
+  if false
+    p :ng
+  end
+__END__
+a = nil
+while a
+  b
+end
+
+__END__
+
+require 'timeout'
+timeout(1){
+  sleep
+}
+
+__END__
+
+Thread.new{
+  i = 0
+  loop{
+    p i+=1
+    sleep 0.1
+  }
+}
+gets
+__END__
+
+a = b = c = false
+p((a and b and c))
+a = b = c = nil
+p((a and b and c))
+
+__END__
+
+a = 0
+  if a > 10
+    a = :then
+  elsif a > 5
+    a = :elsif1
+  elsif a > 0
+    a = :elsif2
+  else
+    a = :else
+  end
+  exit
+__END__
+if a
+  p 1
+end
+__END__
+Thread.new{
+  break
+}.join
+
+__END__
+
+fork do
+  break
+end
+__END__
+pid = fork{
+  p 1
+}
+#Process.waitpid(pid)
+
+__END__
+
+t = Thread.new{
   Thread.stop
 }
 sleep 0.1

Modified: trunk/thread.c
===================================================================
--- trunk/thread.c	2006-02-06 14:52:06 UTC (rev 367)
+++ trunk/thread.c	2006-02-07 05:44:51 UTC (rev 368)
@@ -144,6 +144,7 @@
   GetProcVal(th->first_proc, proc);
 
   th->machine_stack_start = stack_start;
+  th->thgroup = th->vm->thgroup_default;
   
   thread_debug("thread start: %p\n", th);
   
@@ -471,7 +472,6 @@
       VALUE err = th->throwed_errinfo;
       th->throwed_errinfo = 0;
       if(err == eKillSignal){
-        th->status == THREAD_TO_KILL;
         TH_JUMP_TAG(th, TAG_FATAL);
       }
       else{
@@ -793,6 +793,122 @@
   return GET_VM()->main_thread_val;
 }
 
+
+/*
+ *  call-seq:
+ *     Thread.abort_on_exception   => true or false
+ *  
+ *  Returns the status of the global ``abort on exception'' condition.  The
+ *  default is <code>false</code>. When set to <code>true</code>, or if the
+ *  global <code>$DEBUG</code> flag is <code>true</code> (perhaps because the
+ *  command line option <code>-d</code> was specified) all threads will abort
+ *  (the process will <code>exit(0)</code>) if an exception is raised in any
+ *  thread. See also <code>Thread::abort_on_exception=</code>.
+ */
+
+static VALUE
+rb_thread_s_abort_exc()
+{
+  return GET_VM()->thread_abort_on_exception ? Qtrue : Qfalse;
+}
+
+
+/*
+ *  call-seq:
+ *     Thread.abort_on_exception= boolean   => true or false
+ *  
+ *  When set to <code>true</code>, all threads will abort if an exception is
+ *  raised. Returns the new state.
+ *     
+ *     Thread.abort_on_exception = true
+ *     t1 = Thread.new do
+ *       puts  "In new thread"
+ *       raise "Exception from thread"
+ *     end
+ *     sleep(1)
+ *     puts "not reached"
+ *     
+ *  <em>produces:</em>
+ *     
+ *     In new thread
+ *     prog.rb:4: Exception from thread (RuntimeError)
+ *     	from prog.rb:2:in `initialize'
+ *     	from prog.rb:2:in `new'
+ *     	from prog.rb:2
+ */
+
+static VALUE
+rb_thread_s_abort_exc_set(VALUE self, VALUE val)
+{
+  rb_secure(4);
+  GET_VM()->thread_abort_on_exception = RTEST(val);
+  return val;
+}
+
+
+/*
+ *  call-seq:
+ *     thr.abort_on_exception   => true or false
+ *  
+ *  Returns the status of the thread-local ``abort on exception'' condition for
+ *  <i>thr</i>. The default is <code>false</code>. See also
+ *  <code>Thread::abort_on_exception=</code>.
+ */
+
+static VALUE
+rb_thread_abort_exc(VALUE thread)
+{
+  yarv_thread_t *th;
+  GetThreadVal(thread, th);
+  return th->abort_on_exception ? Qtrue : Qfalse;
+}
+
+
+/*
+ *  call-seq:
+ *     thr.abort_on_exception= boolean   => true or false
+ *  
+ *  When set to <code>true</code>, causes all threads (including the main
+ *  program) to abort if an exception is raised in <i>thr</i>. The process will
+ *  effectively <code>exit(0)</code>.
+ */
+
+static VALUE
+rb_thread_abort_exc_set(VALUE thread, VALUE val)
+{
+  yarv_thread_t *th;
+  rb_secure(4);
+
+  GetThreadVal(thread, th);
+  th->abort_on_exception = RTEST(val);
+  return val;
+}
+
+
+/*
+ *  call-seq:
+ *     thr.group   => thgrp or nil
+ *  
+ *  Returns the <code>ThreadGroup</code> which contains <i>thr</i>, or nil if
+ *  the thread is not a member of any group.
+ *     
+ *     Thread.main.group   #=> #<ThreadGroup:0x4029d914>
+ */
+
+VALUE
+rb_thread_group(VALUE thread)
+{
+  yarv_thread_t *th;
+  VALUE group;
+  GetThreadVal(thread, th);
+  group = th->thgroup;
+  
+  if (!group) {
+    group = Qnil;
+  }
+  return group;
+}
+
 static const char *
 thread_status_name(enum yarv_thread_status status)
 {
@@ -902,6 +1018,27 @@
 }
 
 /*
+ *  call-seq:
+ *     thr.safe_level   => integer
+ *  
+ *  Returns the safe level in effect for <i>thr</i>. Setting thread-local safe
+ *  levels can help when implementing sandboxes which run insecure code.
+ *     
+ *     thr = Thread.new { $SAFE = 3; sleep }
+ *     Thread.current.safe_level   #=> 0
+ *     thr.safe_level              #=> 3
+ */
+
+static VALUE
+rb_thread_safe_level(VALUE thread)
+{
+  yarv_thread_t *th;
+  GetThreadVal(thread, th);
+
+  return INT2NUM(th->safe_level);
+}
+
+/*
  * call-seq:
  *   thr.inspect   => string
  *
@@ -1267,8 +1404,197 @@
   return rb_str_new2(buff);
 }
 
+
+
+struct thgroup {
+    int enclosed;
+    VALUE group;
+};
+
+/*
+ * Document-class: ThreadGroup
+ *
+ *  <code>ThreadGroup</code> provides a means of keeping track of a number of
+ *  threads as a group. A <code>Thread</code> can belong to only one
+ *  <code>ThreadGroup</code> at a time; adding a thread to a new group will
+ *  remove it from any previous group.
+ *     
+ *  Newly created threads belong to the same group as the thread from which they
+ *  were created.
+ */
+
+static VALUE thgroup_s_alloc _((VALUE));
+static VALUE
+thgroup_s_alloc(VALUE klass)
+{
+  VALUE group;
+  struct thgroup *data;
+
+  group = Data_Make_Struct(klass, struct thgroup, 0, free, data);
+  data->enclosed = 0;
+  data->group = group;
+
+  return group;
+}
+
+struct thgroup_list_params{
+  VALUE ary;
+  VALUE group;
+};
+
+static int
+thgroup_list_i(st_data_t key, st_data_t val, st_data_t data)
+{
+  VALUE thread = (VALUE)key;
+  VALUE ary = ((struct thgroup_list_params *)data)->ary;
+  VALUE group = ((struct thgroup_list_params *)data)->group;
+  yarv_thread_t *th;
+  GetThreadVal(thread, th);
+
+  if(th->thgroup == group){
+    rb_ary_push(ary, thread);
+  }
+  return ST_CONTINUE;
+}
+
+/*
+ *  call-seq:
+ *     thgrp.list   => array
+ *  
+ *  Returns an array of all existing <code>Thread</code> objects that belong to
+ *  this group.
+ *     
+ *     ThreadGroup::Default.list   #=> [#<Thread:0x401bdf4c run>]
+ */
+
+static VALUE
+thgroup_list(VALUE group)
+{
+  yarv_thread_t *th;
+  VALUE ary = rb_ary_new();
+  struct thgroup_list_params param = {
+    ary, group,
+  };
+  st_foreach(GET_VM()->living_threads, thgroup_list_i, (st_data_t)&param);
+  return ary;
+}
+
+
+/*
+ *  call-seq:
+ *     thgrp.enclose   => thgrp
+ *  
+ *  Prevents threads from being added to or removed from the receiving
+ *  <code>ThreadGroup</code>. New threads can still be started in an enclosed
+ *  <code>ThreadGroup</code>.
+ *     
+ *     ThreadGroup::Default.enclose        #=> #<ThreadGroup:0x4029d914>
+ *     thr = Thread::new { Thread.stop }   #=> #<Thread:0x402a7210 sleep>
+ *     tg = ThreadGroup::new               #=> #<ThreadGroup:0x402752d4>
+ *     tg.add thr
+ *
+ *  <em>produces:</em>
+ *
+ *     ThreadError: can't move from the enclosed thread group
+ */
+
+VALUE
+thgroup_enclose(group)
+    VALUE group;
+{
+  struct thgroup *data;
+
+  Data_Get_Struct(group, struct thgroup, data);
+  data->enclosed = 1;
+
+  return group;
+}
+
+
+/*
+ *  call-seq:
+ *     thgrp.enclosed?   => true or false
+ *  
+ *  Returns <code>true</code> if <em>thgrp</em> is enclosed. See also
+ *  ThreadGroup#enclose.
+ */
+
+static VALUE
+thgroup_enclosed_p(VALUE group)
+{
+  struct thgroup *data;
+
+  Data_Get_Struct(group, struct thgroup, data);
+  if (data->enclosed) return Qtrue;
+  return Qfalse;
+}
+
+
+/*
+ *  call-seq:
+ *     thgrp.add(thread)   => thgrp
+ *  
+ *  Adds the given <em>thread</em> to this group, removing it from any other
+ *  group to which it may have previously belonged.
+ *     
+ *     puts "Initial group is #{ThreadGroup::Default.list}"
+ *     tg = ThreadGroup.new
+ *     t1 = Thread.new { sleep }
+ *     t2 = Thread.new { sleep }
+ *     puts "t1 is #{t1}"
+ *     puts "t2 is #{t2}"
+ *     tg.add(t1)
+ *     puts "Initial group now #{ThreadGroup::Default.list}"
+ *     puts "tg group now #{tg.list}"
+ *     
+ *  <em>produces:</em>
+ *     
+ *     Initial group is #<Thread:0x401bdf4c>
+ *     t1 is #<Thread:0x401b3c90>
+ *     t2 is #<Thread:0x401b3c18>
+ *     Initial group now #<Thread:0x401b3c18>#<Thread:0x401bdf4c>
+ *     tg group now #<Thread:0x401b3c90>
+ */
+
+static VALUE
+thgroup_add(VALUE group, VALUE thread)
+{
+  yarv_thread_t *th;
+  struct thgroup *data;
+
+  rb_secure(4);
+  GetThreadVal(thread, th);
+
+  if (OBJ_FROZEN(group)) {
+    rb_raise(rb_eThreadError, "can't move to the frozen thread group");
+  }
+  Data_Get_Struct(group, struct thgroup, data);
+  if (data->enclosed) {
+    rb_raise(rb_eThreadError, "can't move to the enclosed thread group");
+  }
+  
+  if (!th->thgroup) {
+    return Qnil;
+  }
+  
+  if (OBJ_FROZEN(th->thgroup)) {
+    rb_raise(rb_eThreadError, "can't move from the frozen thread group");
+  }
+  Data_Get_Struct(th->thgroup, struct thgroup, data);
+  if (data->enclosed) {
+    rb_raise(rb_eThreadError, "can't move from the enclosed thread group");
+  }
+
+  th->thgroup = group;
+  return group;
+}
+
+
 void
 Init_yarvthread(){
+  VALUE cThGroup;
+  VALUE thgroup_default;
+
   rb_define_global_function("raw_gets", raw_gets, 0);
 
   rb_define_singleton_method(cYarvThread, "new", yarv_thread_s_new, -2);
@@ -1300,8 +1626,22 @@
   rb_define_method(cYarvThread, "status", rb_thread_status, 0);
   rb_define_method(cYarvThread, "alive?", rb_thread_alive_p, 0);
   rb_define_method(cYarvThread, "stop?", rb_thread_stop_p, 0);
+  rb_define_method(cYarvThread, "abort_on_exception", rb_thread_abort_exc, 0);
+  rb_define_method(cYarvThread, "abort_on_exception=", rb_thread_abort_exc_set, 1);
+  rb_define_method(cYarvThread, "safe_level", rb_thread_safe_level, 0);
+  rb_define_method(cYarvThread, "group", rb_thread_group, 0);
+
   rb_define_method(cYarvThread, "inspect", rb_thread_inspect, 0);
-  
+
+  cThGroup = rb_define_class("ThreadGroup", rb_cObject);
+  rb_define_alloc_func(cThGroup, thgroup_s_alloc);
+  rb_define_method(cThGroup, "list", thgroup_list, 0);
+  rb_define_method(cThGroup, "enclose", thgroup_enclose, 0);
+  rb_define_method(cThGroup, "enclosed?", thgroup_enclosed_p, 0);
+  rb_define_method(cThGroup, "add", thgroup_add, 1);
+  GET_VM()->thgroup_default = thgroup_default = rb_obj_alloc(cThGroup);
+  rb_define_const(cThGroup, "Default", thgroup_default);
+
   Init_native_thread();
   {
     /* main thread setting */

Modified: trunk/vm.c
===================================================================
--- trunk/vm.c	2006-02-06 14:52:06 UTC (rev 367)
+++ trunk/vm.c	2006-02-07 05:44:51 UTC (rev 368)
@@ -643,26 +643,28 @@
 static VALUE *
 lfp_svar(VALUE *lfp, int cnt)
 {
-  NODE *node = (NODE*)lfp[-1];
+  struct RValue *val = (struct RValue *)lfp[-1];
 
-  if((VALUE)node == Qnil){
-    lfp[-1] = (VALUE)(node = NEW_IF(Qnil, Qnil, 0));
-    node->nd_file = 0;
+  if((VALUE)val == Qnil){
+    val = RVALUE(rb_newobj());
+    OBJSETUP(val, 0, T_VALUE);
+    val->v1 = val->v2 = val->v3 = Qnil;
+    lfp[-1] = (VALUE)val;
   }
   
   if(cnt == 0){
-    return &node->u1.value;
+    return &val->v1;
   }
   else if(cnt == 1){
-    return &node->u2.value;
+    return &val->v2;
   }
   else if(cnt == -1){
-    return (VALUE*)&node->nd_file;
+    return &val->basic.klass;
   }
   else{
     VALUE ary;
-    if((ary = node->u3.value) == 0){
-      ary = node->u3.value = rb_ary_new();
+    if((ary = val->v3) == 0){
+      ary = val->v3 = rb_ary_new();
     }
     if(RARRAY(ary)->len <= cnt){
       rb_ary_store(ary, cnt, Qnil);

Modified: trunk/yarvcore.c
===================================================================
--- trunk/yarvcore.c	2006-02-06 14:52:06 UTC (rev 367)
+++ trunk/yarvcore.c	2006-02-07 05:44:51 UTC (rev 368)
@@ -575,6 +575,7 @@
   if(ptr){
     yarv_vm_t *vm = ptr;
     st_foreach(vm->living_threads, vm_mark_each_thread_func, 0);
+    MARK_UNLESS_NULL(vm->thgroup_default);
   }
   MARK_REPORT("<- vm", 0);
 }
@@ -659,6 +660,7 @@
     MARK_UNLESS_NULL(th->first_proc);
     MARK_UNLESS_NULL(th->first_args);
 
+    MARK_UNLESS_NULL(th->thgroup);
     MARK_UNLESS_NULL(th->wait_thread_value);
     MARK_UNLESS_NULL(th->value);
     MARK_UNLESS_NULL(th->errinfo);
@@ -1187,7 +1189,9 @@
 
     th->machine_stack_start = rb_gc_stack_start;
     Init_yarvthread();
-    
+
+    th->thgroup = th->vm->thgroup_default;
+
     vm->living_threads = st_init_numtable();
     st_insert(vm->living_threads, th->self, (st_data_t)th->thread_id);
   }

Modified: trunk/yarvcore.h
===================================================================
--- trunk/yarvcore.h	2006-02-06 14:52:06 UTC (rev 367)
+++ trunk/yarvcore.h	2006-02-07 05:44:51 UTC (rev 368)
@@ -291,7 +291,9 @@
 
   VALUE main_thread_val;
   st_table *living_threads;
+  VALUE thgroup_default;
 
+  int thread_abort_on_exception;
   int exit_code;
   unsigned long trace_flag;
 } yarv_vm_t;
@@ -378,7 +380,8 @@
   int priority;
   
   native_thread_data_t native_thread_data;
-  
+
+  VALUE thgroup;
   VALUE value;
   VALUE wait_thread_value;
 
@@ -409,7 +412,7 @@
 
   /* misc */
   int method_missing_reason;
-  
+  int abort_on_exception;
 } yarv_thread_t;
 
 /** node -> yarv instruction sequence object */

Modified: trunk/yarvtest/test_thread.rb
===================================================================
--- trunk/yarvtest/test_thread.rb	2006-02-06 14:52:06 UTC (rev 367)
+++ trunk/yarvtest/test_thread.rb	2006-02-07 05:44:51 UTC (rev 368)
@@ -118,6 +118,25 @@
       }.value + Thread.current[:a]
     }
   end
-  
+
+  def test_thread_group
+    ae %q{
+      ptg = Thread.current.group
+      Thread.new{
+        ctg = Thread.current.group
+        [ctg.class, ctg == ptg]
+      }.value
+    }
+    ae %q{
+      thg = ThreadGroup.new
+
+      t = Thread.new{
+        thg.add Thread.current
+        sleep
+      }
+      sleep 0.1
+      [thg.list.size, ThreadGroup::Default.list.size]
+    }
+  end
 end
 


-- 
ML: yarv-diff quickml.atdot.net
Info: http://www.atdot.net/~ko1/quickml

[前][次][番号順一覧][スレッド一覧][生データ]