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

ruby-changes:18029

From: shyouhei <ko1@a...>
Date: Thu, 2 Dec 2010 20:08:46 +0900 (JST)
Subject: [ruby-changes:18029] Ruby:r30050 (trunk): * vm.c (ruby_vm_at_exit): new API. This enables extension libs to

shyouhei	2010-12-02 20:06:32 +0900 (Thu, 02 Dec 2010)

  New Revision: 30050

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

  Log:
    * vm.c (ruby_vm_at_exit): new API.  This enables extension libs to
      hook a VM termination.  Right now, because the VM we have is
      process global, most extensions do not deallocate resources and
      leave them to Operating System's reaping userland processes.  But
      in a future we plan to have multiple VMs to run simultaneously in
      a single process (MVM project).  At that stage we can no longer
      rely on OSes and have to manage every resources to be reclaimed
      properly.  So it is.  For a forward-compatibility reason this API
      is introduced now, encouraging you to be as gentle as you can for
      your resources; that is, tidy up your room.
    
    * include/ruby/vm.h: ditto.
    
    * vm_core.h (rb_vm_struct): new field.
    
    * vm.c (vm_init2): initialize above new field.
    
    * eval.c (ruby_cleanup): trigger those hooks.

  Modified files:
    trunk/ChangeLog
    trunk/eval.c
    trunk/include/ruby/vm.h
    trunk/vm.c
    trunk/vm_core.h

Index: include/ruby/vm.h
===================================================================
--- include/ruby/vm.h	(revision 30049)
+++ include/ruby/vm.h	(revision 30050)
@@ -36,6 +36,24 @@
 /* core API */
 int ruby_vm_destruct(ruby_vm_t *vm);
 
+/**
+ * ruby_vm_at_exit registers a function _func_ to be invoked when a VM
+ * passed away.  Functions registered this way runs in reverse order
+ * of registration, just like END {} block does.  The difference is
+ * its timing to be triggered. ruby_vm_at_exit functions runs when a
+ * VM _passed_ _away_, while END {} blocks runs just _before_ a VM
+ * _is_ _passing_ _away_.
+ *
+ * You cannot register a function to another VM than where you are in.
+ * So where to register is intuitive, omitted.  OTOH the argument
+ * _func_ cannot know which VM it is in because at the time of
+ * invocation, the VM has already died and there is no execution
+ * context.  The VM itself is passed as the first argument to it.
+ *
+ * @param[in] func the function to register.
+ */
+void ruby_vm_at_exit(void(*func)(ruby_vm_t *));
+
 #if defined __GNUC__ && __GNUC__ >= 4
 #pragma GCC visibility pop
 #endif
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 30049)
+++ ChangeLog	(revision 30050)
@@ -1,3 +1,24 @@
+Thu Dec  2 19:58:24 2010  URABE Shyouhei  <shyouhei@r...>
+
+	* vm.c (ruby_vm_at_exit): new API.  This enables extension libs to
+	  hook a VM termination.  Right now, because the VM we have is
+	  process global, most extensions do not deallocate resources and
+	  leave them to Operating System's reaping userland processes.  But
+	  in a future we plan to have multiple VMs to run simultaneously in
+	  a single process (MVM project).  At that stage we can no longer
+	  rely on OSes and have to manage every resources to be reclaimed
+	  properly.  So it is.  For a forward-compatibility reason this API
+	  is introduced now, encouraging you to be as gentle as you can for
+	  your resources; that is, tidy up your room.
+
+	* include/ruby/vm.h: ditto.
+
+	* vm_core.h (rb_vm_struct): new field.
+
+	* vm.c (vm_init2): initialize above new field.
+
+	* eval.c (ruby_cleanup): trigger those hooks.
+
 Thu Dec  2 17:00:44 2010  Tanaka Akira  <akr@f...>
 
 	* bignum.c: parenthesize macro arguments.
Index: vm_core.h
===================================================================
--- vm_core.h	(revision 30049)
+++ vm_core.h	(revision 30050)
@@ -317,6 +317,12 @@
 #if defined(ENABLE_VM_OBJSPACE) && ENABLE_VM_OBJSPACE
     struct rb_objspace *objspace;
 #endif
+
+    /*
+     * @shyouhei notes that this is not for storing normal Ruby
+     * objects so do *NOT* mark this when you GC.
+     */
+    struct RArray at_exit;
 } rb_vm_t;
 
 typedef struct {
Index: eval.c
===================================================================
--- eval.c	(revision 30049)
+++ eval.c	(revision 30050)
@@ -129,6 +129,9 @@
     int nerr;
     void rb_threadptr_interrupt(rb_thread_t *th);
     void rb_threadptr_check_signal(rb_thread_t *mth);
+    int i;
+    rb_vm_t *vm = GET_VM();
+    VALUE ary = (VALUE)&vm->at_exit;
 
     rb_threadptr_interrupt(th);
     rb_threadptr_check_signal(th);
@@ -148,6 +151,13 @@
     }
     POP_TAG();
 
+    /* at_exit functions called here; any other place more apropriate
+     * for this purpose? let me know if any. */
+    for (i=0; i<RARRAY_LEN(ary); i++) {
+       ((void(*)(rb_vm_t*))RARRAY_PTR(ary)[i])(vm);
+    }
+    rb_ary_clear(ary);
+
     errs[0] = th->errinfo;
     PUSH_TAG();
     if ((state = EXEC_TAG()) == 0) {
Index: vm.c
===================================================================
--- vm.c	(revision 30049)
+++ vm.c	(revision 30050)
@@ -173,6 +173,14 @@
     return 0;
 }
 
+/* at exit */
+
+void
+ruby_vm_at_exit(void (*func)(rb_vm_t *))
+{
+    rb_ary_push((VALUE)&GET_VM()->at_exit, (VALUE)func);
+}
+
 /* Env */
 
 /*
@@ -1572,6 +1580,8 @@
 {
     MEMZERO(vm, rb_vm_t, 1);
     vm->src_encoding_index = -1;
+    vm->at_exit.basic.flags = (T_ARRAY | RARRAY_EMBED_FLAG) & ~RARRAY_EMBED_LEN_MASK; /* len set 0 */
+    vm->at_exit.basic.klass = 0;
 }
 
 /* Thread */

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

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