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);
cont = Data_Wrap_Struct(rb_cCont, thread_mark, thread_free, th);
scope_dup(ruby_scope);
for (tag=prot_tag; tag; tag=tag->prev) {
scope_dup(tag->scope);
}
th->thread = curr_thread->thread;
th->thgroup = cont_protect;
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);
}
}