/* * call-seq: * callcc {|cont| block } => obj * * Generates a <code>Continuation</code> object, which it passes to the * associated block. Performing a <em>cont</em><code>.call</code> will * cause the <code>callcc</code> to return (as will falling through the * end of the block). The value returned by the <code>callcc</code> is * the value of the block, or the value passed to * <em>cont</em><code>.call</code>. See class <code>Continuation</code> * for more details. Also see <code>Kernel::throw</code> for * an alternative mechanism for unwinding a call stack. */ static VALUE rb_callcc(self) VALUE self; { volatile VALUE cont; rb_thread_t th; volatile rb_thread_t th_save; struct tag *tag; struct RVarmap *vars; THREAD_ALLOC(th); /* must finish th initialization before any possible gc. * brent@mbari.org */ th->thread = curr_thread->thread; th->thgroup = cont_protect; cont = Data_Wrap_Struct(rb_cCont, cc_mark, thread_free, th); scope_dup(ruby_scope); for (tag=prot_tag; tag; tag=tag->prev) { scope_dup(tag->scope); } for (vars = ruby_dyna_vars; vars; vars = vars->next) { if (FL_TEST(vars, DVAR_DONT_RECYCLE)) break; FL_SET(vars, DVAR_DONT_RECYCLE); } th_save = th; if (THREAD_SAVE_CONTEXT(th)) { return th_save->result; } else { return rb_yield(cont); } }