首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

Continuation

Parent:Object

继续对象由Kernel#callcc在+ require + d延续之后生成。 它们拥有一个返回地址和执行上下文,允许非本地从程序中的任何位置返回到callcc块的末尾。 持续有点类似于C的setjmp / longjmp的结构化版本(尽管它们包含更多的状态,所以你可能会认为它们更接近线程)。

例如:

代码语言:javascript
复制
require "continuation"
arr = [ "Freddie", "Herbie", "Ron", "Max", "Ringo" ]
callcc{|cc| $cc = cc}
puts(message = arr.shift)
$cc.call unless message =~ /Max/

产生结果:

代码语言:javascript
复制
Freddie
Herbie
Ron
Max

你也可以用其他方法调用callcc:

代码语言:javascript
复制
require "continuation"

def g
  arr = [ "Freddie", "Herbie", "Ron", "Max", "Ringo" ]
  cc = callcc { |cc| cc }
  puts arr.shift
  return cc, arr.size
end

def f
  c, size = g
  c.call(c) if size > 1
end

f

这个(人为的)例子允许内部循环提前放弃处理:

代码语言:javascript
复制
require "continuation"
callcc {|cont|
  for i in 0..4
    print "\n#{i}: "
    for j in i*5...(i+1)*5
      cont.call() if j == 17
      printf "%3d", j
    end
  end
}
puts

产生结果:

代码语言:javascript
复制
0:   0  1  2  3  4
1:   5  6  7  8  9
2:  10 11 12 13 14
3:  15 16

公共实例方法

contargs, ...()

调用延续。该程序从该callcc块的末尾继续。如果没有给出参数,则原始callcc返回nil。如果给出一个参数,则callcc返回它。否则,返回一个包含args的数组。

代码语言:javascript
复制
callcc {|cont|  cont.call }           #=> nil
callcc {|cont|  cont.call 1 }         #=> 1
callcc {|cont|  cont.call 1, 2, 3 }   #=> [1, 2, 3]
代码语言:javascript
复制
static VALUE
rb_cont_call(int argc, VALUE *argv, VALUE contval)
{
    rb_context_t *cont;
    rb_thread_t *th = GET_THREAD();
    GetContPtr(contval, cont);

    if (cont->saved_thread.self != th->self) {
        rb_raise(rb_eRuntimeError, "continuation called across threads");
    }
    if (cont->saved_thread.protect_tag != th->protect_tag) {
        rb_raise(rb_eRuntimeError, "continuation called across stack rewinding barrier");
    }
    if (cont->saved_thread.fiber) {
        if (th->fiber != cont->saved_thread.fiber) {
            rb_raise(rb_eRuntimeError, "continuation called across fiber");
        }
    }
    rollback_ensure_stack(contval, th->ensure_list, cont->ensure_array);

    cont->argc = argc;
    cont->value = make_passing_arg(argc, argv);

    /* restore `tracing' context. see [Feature #4347] */
    th->trace_arg = cont->saved_thread.trace_arg;
    cont_restore_0(cont, &contval);
    return Qnil; /* unreachable */
}

call(args, ...) Show source

调用延续。 该程序从callcc块的末尾继续。 如果没有给出参数,则原始callcc返回nil。 如果给出一个参数,callcc会返回它。 否则,返回一个包含args的数组。

代码语言:javascript
复制
callcc {|cont|  cont.call }           #=> nil
callcc {|cont|  cont.call 1 }         #=> 1
callcc {|cont|  cont.call 1, 2, 3 }   #=> [1, 2, 3]
代码语言:javascript
复制
static VALUE
rb_cont_call(int argc, VALUE *argv, VALUE contval)
{
    rb_context_t *cont;
    rb_thread_t *th = GET_THREAD();
    GetContPtr(contval, cont);

    if (cont->saved_thread.self != th->self) {
        rb_raise(rb_eRuntimeError, "continuation called across threads");
    }
    if (cont->saved_thread.protect_tag != th->protect_tag) {
        rb_raise(rb_eRuntimeError, "continuation called across stack rewinding barrier");
    }
    if (cont->saved_thread.fiber) {
        if (th->fiber != cont->saved_thread.fiber) {
            rb_raise(rb_eRuntimeError, "continuation called across fiber");
        }
    }
    rollback_ensure_stack(contval, th->ensure_list, cont->ensure_array);

    cont->argc = argc;
    cont->value = make_passing_arg(argc, argv);

    /* restore `tracing' context. see [Feature #4347] */
    th->trace_arg = cont->saved_thread.trace_arg;
    cont_restore_0(cont, &contval);
    return Qnil; /* unreachable */
}

扫码关注腾讯云开发者

领取腾讯云代金券

http://www.vxiaotou.com