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/