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

ruby-changes:17322

From: nobu <ko1@a...>
Date: Fri, 24 Sep 2010 03:06:09 +0900 (JST)
Subject: [ruby-changes:17322] Ruby:r29326 (ruby_1_8): * eval.c (rb_add_threadswitch_hook): wrapper for unofficial APIs

nobu	2010-09-24 03:00:46 +0900 (Fri, 24 Sep 2010)

  New Revision: 29326

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

  Log:
    * eval.c (rb_add_threadswitch_hook): wrapper for unofficial APIs
      in Mac OS X port.  the use of them is strongly discouraged.
    
    * eval.c (rb_remove_threadswitch_hook): ditto.

  Added directories:
    branches/ruby_1_8/ext/-test-/threadswitch/
  Added files:
    branches/ruby_1_8/ext/-test-/threadswitch/extconf.rb
    branches/ruby_1_8/ext/-test-/threadswitch/threadswitch_hook.c
    branches/ruby_1_8/test/-ext-/test_threadswitch_hook.rb
  Modified files:
    branches/ruby_1_8/ChangeLog
    branches/ruby_1_8/configure.in
    branches/ruby_1_8/eval.c
    branches/ruby_1_8/node.h
    branches/ruby_1_8/test/ruby/envutil.rb
    branches/ruby_1_8/version.h

Index: ruby_1_8/ext/-test-/threadswitch/extconf.rb
===================================================================
--- ruby_1_8/ext/-test-/threadswitch/extconf.rb	(revision 0)
+++ ruby_1_8/ext/-test-/threadswitch/extconf.rb	(revision 29326)
@@ -0,0 +1,2 @@
+require 'mkmf'
+create_makefile("-test-/threadswitch/event_hook")

Property changes on: ruby_1_8/ext/-test-/threadswitch/extconf.rb
___________________________________________________________________
Added: svn:eol-style
   + LF

Index: ruby_1_8/ext/-test-/threadswitch/threadswitch_hook.c
===================================================================
--- ruby_1_8/ext/-test-/threadswitch/threadswitch_hook.c	(revision 0)
+++ ruby_1_8/ext/-test-/threadswitch/threadswitch_hook.c	(revision 29326)
@@ -0,0 +1,148 @@
+#include <ruby.h>
+#include <node.h>
+
+/* copied from eval.c */
+static const char *
+get_event_name(rb_event_t event)
+{
+    switch (event) {
+      case RUBY_EVENT_LINE:
+	return "line";
+      case RUBY_EVENT_CLASS:
+	return "class";
+      case RUBY_EVENT_END:
+	return "end";
+      case RUBY_EVENT_CALL:
+	return "call";
+      case RUBY_EVENT_RETURN:
+	return "return";
+      case RUBY_EVENT_C_CALL:
+	return "c-call";
+      case RUBY_EVENT_C_RETURN:
+	return "c-return";
+      case RUBY_EVENT_RAISE:
+	return "raise";
+      case RUBY_EVENT_THREAD_INIT:
+	return "thread-init";
+      case RUBY_EVENT_THREAD_FREE:
+	return "thread-free";
+      case RUBY_EVENT_THREAD_SAVE:
+	return "thread-save";
+      case RUBY_EVENT_THREAD_RESTORE:
+	return "thread-restore";
+      default:
+	return "unknown";
+    }
+}
+
+static VALUE event_callback;
+
+static void
+event_hook(event, node, obj, mid, klass)
+    rb_event_t event;
+    NODE *node;
+    VALUE obj;
+    ID mid;
+    VALUE klass;
+{
+    VALUE block = rb_thread_local_aref(rb_curr_thread->thread, event_callback);
+    if (!NIL_P(block)) {
+	VALUE args = rb_ary_new();
+	rb_ary_push(args, rb_str_new2(get_event_name(event)));
+	rb_ary_push(args, obj);
+	rb_ary_push(args, ID2SYM(mid));
+	rb_ary_push(args, klass);
+	rb_proc_call(block, args);
+    }
+}
+
+static VALUE
+add_event_hook(obj)
+    VALUE obj;
+{
+    rb_add_event_hook(event_hook, RUBY_EVENT_ALL);
+    return obj;
+}
+
+#ifdef RUBY_ENABLE_MACOSX_UNOFFICIAL_THREADSWITCH
+#define get_threadswitch_event_name(thevent) get_event_name((thevent) << RUBY_THREADSWITCH_SHIFT)
+
+static void
+threadswitch_event_hook(event, thread)
+    rb_threadswitch_event_t event;
+    VALUE thread;
+{
+    VALUE block = rb_thread_local_aref(rb_curr_thread->thread, event_callback);
+    if (!NIL_P(block)) {
+	VALUE args = rb_ary_new();
+	rb_ary_push(args, rb_str_new2(get_threadswitch_event_name(event)));
+	rb_ary_push(args, thread);
+	rb_proc_call(block, args);
+    }
+}
+
+static VALUE rb_cThreadSwitchHook;
+
+static VALUE
+threadswitch_add_event_hook(klass)
+    VALUE klass;
+{
+    void *handle = rb_add_threadswitch_hook(threadswitch_event_hook);
+    return Data_Wrap_Struct(klass, 0, rb_remove_threadswitch_hook, handle);
+}
+
+static VALUE
+threadswitch_remove_event_hook(obj)
+    VALUE obj;
+{
+    void *handle = DATA_PTR(obj);
+    DATA_PTR(obj) = 0;
+    if (handle) {
+	rb_remove_threadswitch_hook(handle);
+    }
+    return obj;
+}
+
+static VALUE
+restore_hook(arg)
+    VALUE arg;
+{
+    VALUE *save = (VALUE *)arg;
+    threadswitch_remove_event_hook(save[0]);
+    rb_thread_local_aset(rb_curr_thread->thread, event_callback, save[1]);
+    return Qnil;
+}
+
+static VALUE
+threadswitch_hook(klass)
+    VALUE klass;
+{
+    VALUE save[2];
+    save[1] = rb_thread_local_aref(rb_curr_thread->thread, event_callback);
+    rb_thread_local_aset(rb_curr_thread->thread, event_callback, rb_block_proc());
+    save[0] = threadswitch_add_event_hook(klass);
+    return rb_ensure(rb_yield, save[0], restore_hook, (VALUE)save);
+}
+
+static void
+Init_threadswitch_hook(mEventHook)
+    VALUE mEventHook;
+{
+    rb_cThreadSwitchHook = rb_define_class_under(mEventHook, "ThreadSwitch", rb_cObject);
+    rb_define_singleton_method(rb_cThreadSwitchHook, "add", threadswitch_add_event_hook, 0);
+    rb_define_singleton_method(rb_cThreadSwitchHook, "hook", threadswitch_hook, 0);
+    rb_define_method(rb_cThreadSwitchHook, "remove", threadswitch_remove_event_hook, 0);
+}
+#else
+#define Init_threadswitch_hook(mEventHook) (void)(mEventHook)
+#endif
+
+void
+Init_event_hook()
+{
+    VALUE mEventHook = rb_define_module("EventHook");
+
+    event_callback = rb_intern("rb_event_callback");
+    rb_define_module_function(mEventHook, "hook", add_event_hook, 0);
+    Init_threadswitch_hook(mEventHook);
+}

Property changes on: ruby_1_8/ext/-test-/threadswitch/threadswitch_hook.c
___________________________________________________________________
Added: svn:eol-style
   + LF

Index: ruby_1_8/configure.in
===================================================================
--- ruby_1_8/configure.in	(revision 29325)
+++ ruby_1_8/configure.in	(revision 29326)
@@ -145,6 +145,20 @@
     AC_DEFINE(USE_BUILTIN_FRAME_ADDRESS)
 fi
 
+threadswitch_hook=no
+AC_ARG_ENABLE(macosx-unofficial-threadswitch-hook,
+	AS_HELP_STRING([--enable-macosx-unofficial-threadswitch-hook],
+		[enable Mac OS X unofficial thread switch hook, the use of this option is discouraged.]),
+	[threadswitch_hook=$enableval])
+AS_CASE($threadswitch_hook:$target_os,
+[yes:darwin*], [
+    AC_MSG_WARN([enabled Mac OS X unofficial thread switch hook])
+    AC_DEFINE(RUBY_ENABLE_MACOSX_UNOFFICIAL_THREADSWITCH)
+],
+[yes:*], [
+    AC_MSG_ERROR([--enable-macosx-unofficial-threadswitch-hook is valid only for Mac OS X.])
+])
+
 AC_ARG_PROGRAM
 
 dnl Checks for programs.
Index: ruby_1_8/ChangeLog
===================================================================
--- ruby_1_8/ChangeLog	(revision 29325)
+++ ruby_1_8/ChangeLog	(revision 29326)
@@ -1,3 +1,10 @@
+Fri Sep 24 03:00:26 2010  Nobuyoshi Nakada  <nobu@r...>
+
+	* eval.c (rb_add_threadswitch_hook): wrapper for unofficial APIs
+	  in Mac OS X port.  the use of them is strongly discouraged.
+
+	* eval.c (rb_remove_threadswitch_hook): ditto.
+
 Fri Sep  3 16:42:59 2010  Akinori MUSHA  <knu@i...>
 
 	* parse.y (method_call): Add support for Ruby 1.9 style method
Index: ruby_1_8/version.h
===================================================================
--- ruby_1_8/version.h	(revision 29325)
+++ ruby_1_8/version.h	(revision 29326)
@@ -1,7 +1,7 @@
 #define RUBY_VERSION "1.8.8"
-#define RUBY_RELEASE_DATE "2010-09-03"
+#define RUBY_RELEASE_DATE "2010-09-24"
 #define RUBY_VERSION_CODE 188
-#define RUBY_RELEASE_CODE 20100903
+#define RUBY_RELEASE_CODE 20100924
 #define RUBY_PATCHLEVEL -1
 
 #define RUBY_VERSION_MAJOR 1
@@ -9,7 +9,7 @@
 #define RUBY_VERSION_TEENY 8
 #define RUBY_RELEASE_YEAR 2010
 #define RUBY_RELEASE_MONTH 9
-#define RUBY_RELEASE_DAY 3
+#define RUBY_RELEASE_DAY 24
 
 #define NO_STRING_LITERAL_CONCATENATION 1
 #ifdef RUBY_EXTERN
Index: ruby_1_8/test/ruby/envutil.rb
===================================================================
--- ruby_1_8/test/ruby/envutil.rb	(revision 29325)
+++ ruby_1_8/test/ruby/envutil.rb	(revision 29326)
@@ -25,6 +25,18 @@
     end
   end
   module_function :rubybin
+
+  def verbose_warning
+    class << (stderr = "")
+      alias write <<
+    end
+    stderr, $stderr, verbose, $VERBOSE = $stderr, stderr, $VERBOSE, true
+    yield stderr
+  ensure
+    stderr, $stderr, $VERBOSE = $stderr, stderr, verbose
+    return stderr
+  end
+  module_function :verbose_warning
 end
 
 begin
Index: ruby_1_8/test/-ext-/test_threadswitch_hook.rb
===================================================================
--- ruby_1_8/test/-ext-/test_threadswitch_hook.rb	(revision 0)
+++ ruby_1_8/test/-ext-/test_threadswitch_hook.rb	(revision 29326)
@@ -0,0 +1,16 @@
+require 'test/unit'
+require '-test-/threadswitch/event_hook'
+require 'ruby/envutil'
+
+class Test_ThreadSwitch < Test::Unit::TestCase
+  def test_threadswitch_init
+    threads = []
+    warning = EnvUtil.verbose_warning {
+      EventHook::ThreadSwitch.hook {|name, thread|
+        threads << thread if name == "thread-init"
+      }
+    }
+    assert_match(/not an official API/, warning)
+    assert_operator(threads, :include?, Thread.current)
+  end
+end

Property changes on: ruby_1_8/test/-ext-/test_threadswitch_hook.rb
___________________________________________________________________
Added: svn:eol-style
   + LF

Index: ruby_1_8/eval.c
===================================================================
--- ruby_1_8/eval.c	(revision 29325)
+++ ruby_1_8/eval.c	(revision 29326)
@@ -2663,6 +2663,70 @@
     return -1;
 }
 
+#if defined __APPLE__ && defined __MACH__ && defined RUBY_ENABLE_MACOSX_UNOFFICIAL_THREADSWITCH
+typedef struct threadswitch_hook {
+    rb_threadswitch_hook_func_t func;
+    struct threadswitch_hook *next;
+} rb_threadswitch_hook_t;
+
+static rb_threadswitch_hook_t *threadswitch_hooks;
+
+static void
+call_threadswitch_hook(event, node, thread, mid, klass)
+    rb_event_t event;
+    NODE *node;
+    VALUE thread;
+    ID mid;
+    VALUE klass;
+{
+    rb_threadswitch_hook_t *hook = threadswitch_hooks;
+    rb_threadswitch_event_t thevent = event >> RUBY_THREADSWITCH_SHIFT;
+
+    for (; hook; hook = hook->next) {
+	(*hook->func)(thevent, thread);
+    }
+}
+
+void *
+rb_add_threadswitch_hook(func)
+    rb_threadswitch_hook_func_t func;
+{
+    rb_threadswitch_hook_t *hook;
+    int new_hook = !threadswitch_hooks;
+
+    rb_warn("rb_add_threadswitch_hook is not an official API; use rb_add_event_hook");
+
+    hook = ALLOC(rb_threadswitch_hook_t);
+    hook->func = func;
+    hook->next = threadswitch_hooks;
+    threadswitch_hooks = hook;
+    if (new_hook) {
+	rb_add_event_hook(call_threadswitch_hook, RUBY_EVENT_THREAD_ALL);
+    }
+
+    return hook;
+}
+
+void
+rb_remove_threadswitch_hook(handle)
+    void *handle;
+{
+    rb_threadswitch_hook_t **hook_p, *hook;
+
+    for (hook_p = &threadswitch_hooks; *hook_p; hook_p = &hook->next) {
+	hook = *hook_p;
+	if (hook == (rb_threadswitch_hook_t*)handle) {
+	    *hook_p = hook->next;
+	    xfree(hook);
+	    if (!threadswitch_hooks) {
+		rb_remove_event_hook(call_threadswitch_hook);
+	    }
+	    break;
+	}
+    }
+}
+#endif
+
 /*
  *  call-seq:
  *     set_trace_func(proc)    => proc
Index: ruby_1_8/node.h
===================================================================
--- ruby_1_8/node.h	(revision 29325)
+++ ruby_1_8/node.h	(revision 29326)
@@ -384,6 +384,21 @@
 int rb_remove_event_hook _((rb_event_hook_func_t));
 extern const rb_event_t rb_event_all;
 
+#if defined RUBY_ENABLE_MACOSX_UNOFFICIAL_THREADSWITCH
+typedef rb_event_t rb_threadswitch_event_t;
+
+#define RUBY_THREADSWITCH_SHIFT 8
+#define RUBY_THREADSWITCH_INIT    (RUBY_EVENT_THREAD_INIT>>RUBY_THREADSWITCH_SHIFT)
+#define RUBY_THREADSWITCH_FREE    (RUBY_EVENT_THREAD_FREE>>RUBY_THREADSWITCH_SHIFT)
+#define RUBY_THREADSWITCH_SAVE    (RUBY_EVENT_THREAD_SAVE>>RUBY_THREADSWITCH_SHIFT)
+#define RUBY_THREADSWITCH_RESTORE (RUBY_EVENT_THREAD_RESTORE>>RUBY_THREADSWITCH_SHIFT)
+
+typedef void (*rb_threadswitch_hook_func_t) _((rb_threadswitch_event_t,VALUE));
+
+DEPRECATED(void *rb_add_threadswitch_hook _((rb_threadswitch_hook_func_t func)));
+DEPRECATED(void rb_remove_threadswitch_hook _((void *handle)));
+#endif
+
 #if defined(HAVE_GETCONTEXT) && defined(HAVE_SETCONTEXT)
 #include <ucontext.h>
 #define USE_CONTEXT

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

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