callcc()
public
Generates a Continuation object, which it
passes to the associated block. Performing a cont.call will cause
the callcc to return (as will falling
through the end of the block). The value returned by the callcc is the value of the block, or the
value passed to cont.call. See class Continuation for more details. Also see
Kernel::throw for an alternative mechanism for unwinding a call stack.
Show source
/*
* 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);
}
}