6 #include "eval_intern.h"
11 rb_call_end_proc(VALUE data
)
13 rb_proc_call(data
, rb_ary_new());
18 * at_exit { block } -> proc
20 * Converts _block_ to a +Proc+ object (and therefore
21 * binds it at the point of call) and registers it for execution when
22 * the program exits. If multiple handlers are registered, they are
23 * executed in reverse order of registration.
25 * def do_at_exit(str1)
26 * at_exit { print str1 }
28 * at_exit { puts "cruel world" }
29 * do_at_exit("goodbye ")
42 if (!rb_block_given_p()) {
43 rb_raise(rb_eArgError
, "called without a block");
45 proc
= rb_block_proc();
46 rb_set_end_proc(rb_call_end_proc
, proc
);
50 struct end_proc_data
{
54 struct end_proc_data
*next
;
57 static struct end_proc_data
*end_procs
, *ephemeral_end_procs
, *tmp_end_procs
;
60 rb_set_end_proc(void (*func
)(VALUE
), VALUE data
)
62 struct end_proc_data
*link
= ALLOC(struct end_proc_data
);
63 struct end_proc_data
**list
;
64 rb_thread_t
*th
= GET_THREAD();
66 if (th
->top_wrapper
) {
67 list
= &ephemeral_end_procs
;
75 link
->safe
= rb_safe_level();
80 rb_mark_end_proc(void)
82 struct end_proc_data
*link
;
86 rb_gc_mark(link
->data
);
89 link
= ephemeral_end_procs
;
91 rb_gc_mark(link
->data
);
96 rb_gc_mark(link
->data
);
102 rb_exec_end_proc(void)
104 struct end_proc_data
*link
, *tmp
;
106 volatile int safe
= rb_safe_level();
108 while (ephemeral_end_procs
) {
109 tmp_end_procs
= link
= ephemeral_end_procs
;
110 ephemeral_end_procs
= 0;
113 if ((status
= EXEC_TAG()) == 0) {
114 rb_set_safe_level_force(link
->safe
);
115 (*link
->func
) (link
->data
);
119 error_handle(status
);
122 tmp_end_procs
= link
= link
->next
;
127 tmp_end_procs
= link
= end_procs
;
131 if ((status
= EXEC_TAG()) == 0) {
132 rb_set_safe_level_force(link
->safe
);
133 (*link
->func
) (link
->data
);
137 error_handle(status
);
140 tmp_end_procs
= link
= link
->next
;
144 rb_set_safe_level_force(safe
);
150 rb_define_global_function("at_exit", rb_f_at_exit
, 0);