mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
* 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. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@30050 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
cf39e78e1f
commit
51da92ea12
5 changed files with 65 additions and 0 deletions
21
ChangeLog
21
ChangeLog
|
@ -1,3 +1,24 @@
|
|||
Thu Dec 2 19:58:24 2010 URABE Shyouhei <shyouhei@ruby-lang.org>
|
||||
|
||||
* 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@fsij.org>
|
||||
|
||||
* bignum.c: parenthesize macro arguments.
|
||||
|
|
10
eval.c
10
eval.c
|
@ -129,6 +129,9 @@ ruby_cleanup(volatile int ex)
|
|||
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 @@ ruby_cleanup(volatile int ex)
|
|||
}
|
||||
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) {
|
||||
|
|
|
@ -36,6 +36,24 @@ typedef struct rb_vm_struct ruby_vm_t;
|
|||
/* 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
|
||||
|
|
10
vm.c
10
vm.c
|
@ -173,6 +173,14 @@ vm_get_ruby_level_caller_cfp(rb_thread_t *th, rb_control_frame_t *cfp)
|
|||
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 @@ vm_init2(rb_vm_t *vm)
|
|||
{
|
||||
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 */
|
||||
|
|
|
@ -317,6 +317,12 @@ typedef struct rb_vm_struct {
|
|||
#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 {
|
||||
|
|
Loading…
Reference in a new issue