~ubuntu-branches/ubuntu/intrepid/ruby1.9/intrepid-updates

« back to all changes in this revision

Viewing changes to cont.c

  • Committer: Bazaar Package Importer
  • Author(s): Matthias Klose
  • Date: 2007-09-04 16:01:17 UTC
  • mfrom: (1.1.8 upstream)
  • Revision ID: james.westby@ubuntu.com-20070904160117-i15zckg2nhxe9fyw
Tags: 1.9.0+20070830-2ubuntu1
* Sync from Debian; remaining changes:
  - Add -g to CFLAGS.
* Fixes build failure on ia64.
* Fixes build failure with gcc-4.2 on lpia.
* Robustify check for target_os, fixing build failure on lpia.
* Set Ubuntu maintainer address.

Show diffs side-by-side

added added

removed removed

Lines of Context:
3
3
  cont.c - 
4
4
 
5
5
  $Author: ko1 $
6
 
  $Date: 2007-06-06 10:55:09 +0900 (水, 06  6月 2007) $
 
6
  $Date: 2007-08-26 12:31:20 +0900 (日, 26  8月 2007) $
7
7
  created at: Thu May 23 09:03:43 2007
8
8
 
9
9
  Copyright (C) 2007 Koichi Sasada
10
10
 
11
11
**********************************************************************/
12
12
 
13
 
#include "ruby.h"
14
 
#include "yarvcore.h"
 
13
#include "ruby/ruby.h"
 
14
#include "vm_core.h"
15
15
#include "gc.h"
16
16
#include "eval_intern.h"
17
17
 
18
18
typedef struct rb_context_struct {
19
19
    VALUE self;
20
20
    VALUE value;
21
 
    VALUE prev; /* for fiber */
22
21
    VALUE *vm_stack;
23
22
    VALUE *machine_stack;
24
23
    VALUE *machine_stack_src;
 
24
#ifdef __ia64
 
25
    VALUE *machine_register_stack;
 
26
    VALUE *machine_register_stack_src;
 
27
    int machine_register_stack_size;
 
28
#endif
25
29
    rb_thread_t saved_thread;
26
30
    rb_jmpbuf_t jmpbuf;
27
31
    int machine_stack_size;
 
32
    /* for cont */
 
33
    VALUE prev;
28
34
    int alive;
29
35
} rb_context_t;
30
36
 
31
 
VALUE rb_cCont;
32
 
VALUE rb_cFiber;
33
 
VALUE rb_eFiberError;
 
37
static VALUE rb_cContinuation;
 
38
static VALUE rb_cFiber;
 
39
static VALUE rb_eFiberError;
34
40
 
35
41
#define GetContPtr(obj, ptr)  \
36
42
  Data_Get_Struct(obj, rb_context_t, ptr)
42
48
static void
43
49
cont_mark(void *ptr)
44
50
{
45
 
    MARK_REPORT_ENTER("cont");
 
51
    RUBY_MARK_ENTER("cont");
46
52
    if (ptr) {
47
53
        rb_context_t *cont = ptr;
48
54
        rb_gc_mark(cont->value);
49
55
        rb_gc_mark(cont->prev);
50
 
 
51
56
        rb_thread_mark(&cont->saved_thread);
52
57
 
53
58
        if (cont->vm_stack) {
59
64
            rb_gc_mark_locations(cont->machine_stack,
60
65
                                 cont->machine_stack + cont->machine_stack_size);
61
66
        }
 
67
#ifdef __ia64
 
68
        if (cont->machine_register_stack) {
 
69
            rb_gc_mark_locations(cont->machine_register_stack,
 
70
                                 cont->machine_register_stack + cont->machine_register_stack_size);
 
71
        }
 
72
#endif
62
73
    }
63
 
    MARK_REPORT_LEAVE("cont");
 
74
    RUBY_MARK_LEAVE("cont");
64
75
}
65
76
 
66
77
static void
67
78
cont_free(void *ptr)
68
79
{
69
 
    FREE_REPORT_ENTER("cont");
 
80
    RUBY_FREE_ENTER("cont");
70
81
    if (ptr) {
71
82
        rb_context_t *cont = ptr;
72
 
        FREE_UNLESS_NULL(cont->saved_thread.stack);
73
 
        FREE_UNLESS_NULL(cont->machine_stack);
74
 
        FREE_UNLESS_NULL(cont->vm_stack);
 
83
        RUBY_FREE_UNLESS_NULL(cont->saved_thread.stack);
 
84
        RUBY_FREE_UNLESS_NULL(cont->machine_stack);
 
85
#ifdef __ia64
 
86
        RUBY_FREE_UNLESS_NULL(cont->machine_register_stack);
 
87
#endif
 
88
        RUBY_FREE_UNLESS_NULL(cont->vm_stack);
75
89
        ruby_xfree(ptr);
76
90
    }
77
 
    FREE_REPORT_LEAVE("cont");
 
91
    RUBY_FREE_LEAVE("cont");
78
92
}
79
93
 
80
94
static void
81
95
cont_save_machine_stack(rb_thread_t *th, rb_context_t *cont)
82
96
{
83
97
    int size;
84
 
 
85
 
    rb_gc_set_stack_end(&th->machine_stack_end);
 
98
    rb_thread_t *sth = &cont->saved_thread;
 
99
 
 
100
    SET_MACHINE_STACK_END(&th->machine_stack_end);
 
101
#ifdef __ia64
 
102
    th->machine_register_stack_end = rb_ia64_bsp();
 
103
#endif
 
104
 
86
105
    if (th->machine_stack_start > th->machine_stack_end) {
87
106
        size = cont->machine_stack_size = th->machine_stack_start - th->machine_stack_end;
88
107
        cont->machine_stack_src = th->machine_stack_end;
100
119
    }
101
120
 
102
121
    MEMCPY(cont->machine_stack, cont->machine_stack_src, VALUE, size);
 
122
 
 
123
#ifdef __ia64
 
124
    rb_ia64_flushrs();
 
125
    size = cont->machine_register_stack_size = th->machine_register_stack_end - th->machine_register_stack_start;
 
126
    cont->machine_register_stack_src = th->machine_register_stack_start;
 
127
    if (cont->machine_register_stack) {
 
128
        REALLOC_N(cont->machine_register_stack, VALUE, size);
 
129
    }
 
130
    else {
 
131
        cont->machine_register_stack = ALLOC_N(VALUE, size);
 
132
    }
 
133
 
 
134
    MEMCPY(cont->machine_register_stack, cont->machine_register_stack_src, VALUE, size);
 
135
#endif
 
136
 
 
137
    sth->machine_stack_start = sth->machine_stack_end = 0;
 
138
#ifdef __ia64
 
139
    sth->machine_register_stack_start = sth->machine_register_stack_end = 0;
 
140
#endif
103
141
}
104
142
 
105
143
static rb_context_t *
107
145
{
108
146
    rb_context_t *cont;
109
147
    volatile VALUE contval;
110
 
    rb_thread_t *th = GET_THREAD(), *sth;
 
148
    rb_thread_t *th = GET_THREAD();
111
149
 
112
150
    contval = Data_Make_Struct(klass, rb_context_t,
113
151
                               cont_mark, cont_free, cont);
 
152
 
114
153
    cont->self = contval;
115
154
    cont->alive = Qtrue;
116
155
 
117
 
    /* save context */
 
156
    /* save thread context */
118
157
    cont->saved_thread = *th;
119
 
    sth = &cont->saved_thread;
120
158
 
121
159
    return cont;
122
160
}
123
161
 
124
 
void th_stack_to_heap(rb_thread_t *th);
 
162
void vm_stack_to_heap(rb_thread_t *th);
125
163
 
126
164
static VALUE
127
165
cont_capture(volatile int *stat)
128
166
{
129
167
    rb_context_t *cont;
130
 
    rb_thread_t *th;
 
168
    rb_thread_t *th = GET_THREAD(), *sth;
 
169
    volatile VALUE contval;
131
170
 
132
 
    th_stack_to_heap(GET_THREAD());
133
 
    cont = cont_new(rb_cCont);
134
 
    th = &cont->saved_thread;
 
171
    vm_stack_to_heap(th);
 
172
    cont = cont_new(rb_cContinuation);
 
173
    contval = cont->self;
 
174
    sth = &cont->saved_thread;
135
175
 
136
176
    cont->vm_stack = ALLOC_N(VALUE, th->stack_size);
137
177
    MEMCPY(cont->vm_stack, th->stack, VALUE, th->stack_size);
138
 
    th->stack = 0;
 
178
    sth->stack = 0;
139
179
 
140
180
    cont_save_machine_stack(th, cont);
141
181
 
169
209
    }
170
210
    else {
171
211
        /* continuation */
 
212
        VALUE fib;
 
213
 
 
214
        th->fiber = sth->fiber;
 
215
        fib = th->fiber ? th->fiber : th->root_fiber;
 
216
 
 
217
        if (fib) {
 
218
            rb_context_t *fcont;
 
219
            GetContPtr(fib, fcont);
 
220
            th->stack_size = fcont->saved_thread.stack_size;
 
221
            th->stack = fcont->saved_thread.stack;
 
222
        }
172
223
        MEMCPY(th->stack, cont->vm_stack, VALUE, sth->stack_size);
173
 
        th->fiber = sth->fiber;
174
224
    }
175
225
 
176
226
    th->cfp = sth->cfp;
184
234
    th->first_proc = sth->first_proc;
185
235
 
186
236
    /* restore machine stack */
 
237
#ifdef _M_AMD64
 
238
    {
 
239
        /* workaround for x64 SEH */
 
240
        jmp_buf buf;
 
241
        setjmp(buf);
 
242
        ((_JUMP_BUFFER*)(&cont->jmpbuf))->Frame =
 
243
            ((_JUMP_BUFFER*)(&buf))->Frame;
 
244
    }
 
245
#endif
187
246
    if (cont->machine_stack_src) {
188
247
        MEMCPY(cont->machine_stack_src, cont->machine_stack,
189
248
               VALUE, cont->machine_stack_size);
190
249
    }
191
250
 
 
251
#ifdef __ia64
 
252
    if (cont->machine_register_stack_src) {
 
253
        MEMCPY(cont->machine_register_stack_src, cont->machine_register_stack,
 
254
               VALUE, cont->machine_register_stack_size);
 
255
    }
 
256
#endif
 
257
 
192
258
    ruby_longjmp(cont->jmpbuf, 1);
193
259
}
194
260
 
195
261
NORETURN(NOINLINE(static void cont_restore_0(rb_context_t *, VALUE *)));
196
262
 
 
263
#ifdef __ia64
 
264
#define C(a) rse_##a##0, rse_##a##1, rse_##a##2, rse_##a##3, rse_##a##4
 
265
#define E(a) rse_##a##0= rse_##a##1= rse_##a##2= rse_##a##3= rse_##a##4
 
266
static volatile int C(a), C(b), C(c), C(d), C(e);
 
267
static volatile int C(f), C(g), C(h), C(i), C(j);
 
268
static volatile int C(k), C(l), C(m), C(n), C(o);
 
269
static volatile int C(p), C(q), C(r), C(s), C(t);
 
270
int rb_dummy_false = 0;
 
271
NORETURN(NOINLINE(static void register_stack_extend(rb_context_t *, VALUE *)));
 
272
static void
 
273
register_stack_extend(rb_context_t *cont, VALUE *curr_bsp)
 
274
{
 
275
    if (rb_dummy_false) {
 
276
        /* use registers as much as possible */
 
277
        E(a) = E(b) = E(c) = E(d) = E(e) =
 
278
        E(f) = E(g) = E(h) = E(i) = E(j) =
 
279
        E(k) = E(l) = E(m) = E(n) = E(o) =
 
280
        E(p) = E(q) = E(r) = E(s) = E(t) = 0;
 
281
        E(a) = E(b) = E(c) = E(d) = E(e) =
 
282
        E(f) = E(g) = E(h) = E(i) = E(j) =
 
283
        E(k) = E(l) = E(m) = E(n) = E(o) =
 
284
        E(p) = E(q) = E(r) = E(s) = E(t) = 0;
 
285
    }
 
286
    if (curr_bsp < cont->machine_register_stack_src+cont->machine_register_stack_size) {
 
287
        register_stack_extend(cont, (VALUE*)rb_ia64_bsp());
 
288
    }
 
289
    cont_restore_1(cont);
 
290
}
 
291
#undef C
 
292
#undef E
 
293
#endif
 
294
 
197
295
static void
198
296
cont_restore_0(rb_context_t *cont, VALUE *addr_in_prev_frame)
199
297
{
224
322
        }
225
323
#endif
226
324
    }
 
325
#ifdef __ia64
 
326
    register_stack_extend(cont, (VALUE*)rb_ia64_bsp());
 
327
#else
227
328
    cont_restore_1(cont);
 
329
#endif
228
330
}
229
331
 
230
332
/*
348
450
        rb_context_t *fcont;
349
451
        GetContPtr(cont->saved_thread.fiber, fcont);
350
452
 
 
453
        if (th->fiber != cont->saved_thread.fiber) {
 
454
            rb_raise(rb_eRuntimeError, "continuation called across fiber");
 
455
        }
 
456
        
351
457
        if (!fcont->alive) {
352
458
            rb_raise(rb_eRuntimeError, "continuation called dead fiber");
353
459
        }
355
461
 
356
462
    cont->value = make_passing_arg(argc, argv);
357
463
 
358
 
    cont_restore_0(cont, (VALUE *)&cont);
 
464
    cont_restore_0(cont, &contval);
359
465
    return Qnil; /* unreachable */
360
466
}
361
467
 
363
469
/* fiber */
364
470
/*********/
365
471
 
366
 
#define FIBER_STACK_SIZE (4 * 1024)
 
472
#define FIBER_VM_STACK_SIZE (4 * 1024)
367
473
 
368
474
static VALUE
369
 
rb_fiber_s_new(VALUE self)
 
475
fiber_alloc(VALUE klass, VALUE proc)
370
476
{
371
 
    rb_context_t *cont = cont_new(self);
 
477
    rb_context_t *cont = cont_new(klass);
 
478
    VALUE contval = cont->self;
372
479
    rb_thread_t *th = &cont->saved_thread;
373
480
 
374
481
    /* initialize */
376
483
    cont->vm_stack = 0;
377
484
 
378
485
    th->stack = 0;
379
 
    th->stack_size = FIBER_STACK_SIZE;
 
486
    th->stack_size = FIBER_VM_STACK_SIZE;
380
487
    th->stack = ALLOC_N(VALUE, th->stack_size);
 
488
 
381
489
    th->cfp = (void *)(th->stack + th->stack_size);
382
490
    th->cfp--;
383
491
    th->cfp->pc = 0;
387
495
    *th->cfp->lfp = 0;
388
496
    th->cfp->dfp = th->stack;
389
497
    th->cfp->self = Qnil;
390
 
    th->cfp->magic = 0;
 
498
    th->cfp->flag = 0;
391
499
    th->cfp->iseq = 0;
392
500
    th->cfp->proc = 0;
393
501
    th->cfp->block_iseq = 0;
 
502
    th->tag = 0;
394
503
 
395
 
    th->first_proc = rb_block_proc();
 
504
    th->first_proc = proc;
396
505
 
397
506
    MEMCPY(&cont->jmpbuf, &th->root_jmpbuf, rb_jmpbuf_t, 1);
398
507
 
399
 
    return cont->self;
400
 
}
401
 
 
402
 
static VALUE rb_fiber_yield(int argc, VALUE *args, VALUE fval);
 
508
    return contval;
 
509
}
 
510
 
 
511
VALUE
 
512
rb_fiber_new(VALUE (*func)(ANYARGS), VALUE obj)
 
513
{
 
514
    return fiber_alloc(rb_cFiber, rb_proc_new(func, obj));
 
515
}
 
516
 
 
517
static VALUE
 
518
rb_fiber_s_new(VALUE self)
 
519
{
 
520
    return fiber_alloc(self, rb_block_proc());
 
521
}
 
522
 
 
523
static VALUE
 
524
return_fiber(void)
 
525
{
 
526
    rb_context_t *cont;
 
527
    VALUE curr = rb_fiber_current();
 
528
    GetContPtr(curr, cont);
 
529
 
 
530
    if (cont->prev == Qnil) {
 
531
        rb_thread_t *th = GET_THREAD();
 
532
 
 
533
        if (th->root_fiber != curr) {
 
534
            return th->root_fiber;
 
535
        }
 
536
        else {
 
537
            rb_raise(rb_eFiberError, "can't yield from root fiber");
 
538
        }
 
539
    }
 
540
    else {
 
541
        VALUE prev = cont->prev;
 
542
        cont->prev = Qnil;
 
543
        return prev;
 
544
    }
 
545
}
 
546
 
 
547
VALUE rb_fiber_transfer(VALUE fib, int argc, VALUE *argv);
403
548
 
404
549
static void
405
550
rb_fiber_terminate(rb_context_t *cont)
406
551
{
407
 
    rb_context_t *prev_cont;
408
552
    VALUE value = cont->value;
409
 
 
410
 
    GetContPtr(cont->prev, prev_cont);
411
 
 
412
553
    cont->alive = Qfalse;
413
 
 
414
 
 
415
 
    if (prev_cont->alive == Qfalse) {
416
 
        rb_fiber_yield(1, &value, GET_THREAD()->root_fiber);
417
 
    }
418
 
    else {
419
 
        rb_fiber_yield(1, &value, cont->prev);
420
 
    }
 
554
    rb_fiber_transfer(return_fiber(), 1, &value);
421
555
}
422
556
 
423
557
void
429
563
    VALUE args;
430
564
    int state;
431
565
 
432
 
    th->tag = 0;
433
 
 
 
566
    GetContPtr(th->fiber, cont);
434
567
    TH_PUSH_TAG(th);
435
568
    if ((state = EXEC_TAG()) == 0) {
436
 
        GetContPtr(th->fiber, cont);
437
569
        GetProcPtr(cont->saved_thread.first_proc, proc);
438
570
        args = cont->value;
439
571
        cont->value = Qnil;
441
573
        th->local_lfp = proc->block.lfp;
442
574
        th->local_svar = Qnil;
443
575
 
444
 
        cont->value = th_invoke_proc(th, proc, proc->block.self, 1, &args);
 
576
        cont->value = vm_invoke_proc(th, proc, proc->block.self, 1, &args);
445
577
    }
446
578
    TH_POP_TAG();
447
579
 
448
580
    if (state) {
449
 
        th->thrown_errinfo = th_make_jump_tag_but_local_jump(state, th->errinfo);
 
581
        if (TAG_RAISE) {
 
582
            th->thrown_errinfo = th->errinfo;
 
583
        }
 
584
        else {
 
585
            th->thrown_errinfo =
 
586
              vm_make_jump_tag_but_local_jump(state, th->errinfo);
 
587
        }
450
588
        th->interrupt_flag = 1;
451
589
    }
452
590
 
454
592
    rb_bug("rb_fiber_start: unreachable");
455
593
}
456
594
 
457
 
static VALUE
458
 
rb_fiber_current(rb_thread_t *th)
 
595
VALUE
 
596
rb_fiber_current()
459
597
{
 
598
    rb_thread_t *th = GET_THREAD();
460
599
    if (th->fiber == 0) {
461
600
        /* save root */
462
 
        th->root_fiber = th->fiber = cont_new(rb_cFiber)->self;
 
601
        rb_context_t *cont = cont_new(rb_cFiber);
 
602
        cont->prev = Qnil;
 
603
        th->root_fiber = th->fiber = cont->self;
463
604
    }
464
605
    return th->fiber;
465
606
}
477
618
    else {
478
619
        /* create current fiber */
479
620
        cont = cont_new(rb_cFiber); /* no need to allocate vm stack */
 
621
        cont->prev = Qnil;
480
622
        th->root_fiber = th->fiber = cont->self;
481
623
    }
482
624
 
483
 
    if (cont->alive) {
484
 
        next_cont->prev = cont->self;
485
 
    }
486
625
    cont_save_machine_stack(th, cont);
487
626
 
488
627
    if (ruby_setjmp(cont->jmpbuf)) {
495
634
    }
496
635
}
497
636
 
498
 
static VALUE
499
 
rb_fiber_yield(int argc, VALUE *argv, VALUE fval)
 
637
static inline VALUE
 
638
fiber_switch(VALUE fib, int argc, VALUE *argv, int is_resume)
500
639
{
501
640
    VALUE value;
502
641
    rb_context_t *cont;
503
642
    rb_thread_t *th = GET_THREAD();
504
643
 
505
 
    GetContPtr(fval, cont);
 
644
    GetContPtr(fib, cont);
506
645
 
507
646
    if (cont->saved_thread.self != th->self) {
508
647
        rb_raise(rb_eFiberError, "fiber called across threads");
509
648
    }
510
 
    if (cont->saved_thread.trap_tag != th->trap_tag) {
 
649
    else if (cont->saved_thread.trap_tag != th->trap_tag) {
511
650
        rb_raise(rb_eFiberError, "fiber called across trap");
512
651
    }
513
 
    if (!cont->alive) {
 
652
    else if (!cont->alive) {
514
653
        rb_raise(rb_eFiberError, "dead fiber called");
515
654
    }
516
655
 
 
656
    if (is_resume) {
 
657
        cont->prev = rb_fiber_current();
 
658
    }
 
659
 
517
660
    cont->value = make_passing_arg(argc, argv);
518
661
 
519
662
    if ((value = cont_store(cont)) == Qundef) {
520
 
        cont_restore_0(cont, (VALUE *)&cont);
521
 
        rb_bug("rb_fiber_yield: unreachable");
 
663
        cont_restore_0(cont, &value);
 
664
        rb_bug("rb_fiber_resume: unreachable");
522
665
    }
523
666
 
 
667
    RUBY_VM_CHECK_INTS();
 
668
 
524
669
    return value;
525
670
}
526
671
 
527
 
static VALUE
528
 
rb_fiber_prev(VALUE fval)
529
 
{
530
 
    rb_context_t *cont;
531
 
    GetContPtr(fval, cont);
532
 
    return cont->prev;
533
 
}
534
 
 
535
 
static VALUE
536
 
rb_fiber_alive_p(VALUE fval)
537
 
{
538
 
    rb_context_t *cont;
539
 
    GetContPtr(fval, cont);
 
672
VALUE
 
673
rb_fiber_transfer(VALUE fib, int argc, VALUE *argv)
 
674
{
 
675
    return fiber_switch(fib, argc, argv, 0);
 
676
}
 
677
 
 
678
VALUE
 
679
rb_fiber_resume(VALUE fib, int argc, VALUE *argv)
 
680
{
 
681
    rb_context_t *cont;
 
682
    GetContPtr(fib, cont);
 
683
 
 
684
    if (cont->prev != Qnil) {
 
685
        rb_raise(rb_eFiberError, "double resume");
 
686
    }
 
687
 
 
688
    return fiber_switch(fib, argc, argv, 1);
 
689
}
 
690
 
 
691
VALUE
 
692
rb_fiber_yield(int argc, VALUE *argv)
 
693
{
 
694
    return rb_fiber_transfer(return_fiber(), argc, argv);
 
695
}
 
696
 
 
697
VALUE
 
698
rb_fiber_alive_p(VALUE fib)
 
699
{
 
700
    rb_context_t *cont;
 
701
    GetContPtr(fib, cont);
540
702
    return cont->alive;
541
703
}
542
704
 
543
705
static VALUE
 
706
rb_fiber_m_resume(int argc, VALUE *argv, VALUE fib)
 
707
{
 
708
    return rb_fiber_resume(fib, argc, argv);
 
709
}
 
710
 
 
711
static VALUE
 
712
rb_fiber_m_transfer(int argc, VALUE *argv, VALUE fib)
 
713
{
 
714
    return rb_fiber_transfer(fib, argc, argv);
 
715
}
 
716
 
 
717
static VALUE
 
718
rb_fiber_s_yield(int argc, VALUE *argv, VALUE klass)
 
719
{
 
720
    return rb_fiber_yield(argc, argv);
 
721
}
 
722
 
 
723
static VALUE
544
724
rb_fiber_s_current(VALUE klass)
545
725
{
546
 
    return rb_fiber_current(GET_THREAD());
547
 
}
548
 
 
549
 
static VALUE
550
 
rb_fiber_s_prev(VALUE klass)
551
 
{
552
 
    return rb_fiber_prev(rb_fiber_s_current(Qnil));
553
 
}
554
 
 
555
 
static VALUE
556
 
rb_fiber_s_yield(int argc, VALUE *argv, VALUE fval)
557
 
{
558
 
    return rb_fiber_yield(argc, argv, rb_fiber_s_prev(Qnil));
 
726
    return rb_fiber_current();
559
727
}
560
728
 
561
729
void
562
730
Init_Cont(void)
563
731
{
564
 
    rb_cCont = rb_define_class("Continuation", rb_cObject);
565
 
    rb_undef_alloc_func(rb_cCont);
566
 
    rb_undef_method(CLASS_OF(rb_cCont), "new");
567
 
    rb_define_method(rb_cCont, "call", rb_cont_call, -1);
568
 
    rb_define_method(rb_cCont, "[]", rb_cont_call, -1);
569
 
    rb_define_global_function("callcc", rb_callcc, 0);
570
 
 
571
732
    rb_cFiber = rb_define_class("Fiber", rb_cObject);
572
733
    rb_undef_alloc_func(rb_cFiber);
573
 
    rb_define_method(rb_cFiber, "yield", rb_fiber_yield, -1);
574
 
    rb_define_method(rb_cFiber, "prev", rb_fiber_prev, 0);
 
734
    rb_eFiberError = rb_define_class("FiberError", rb_eStandardError);
 
735
}
 
736
 
 
737
void
 
738
Init_Continuation_body(void)
 
739
{
 
740
    rb_cContinuation = rb_define_class("Continuation", rb_cObject);
 
741
    rb_undef_alloc_func(rb_cContinuation);
 
742
    rb_undef_method(CLASS_OF(rb_cContinuation), "new");
 
743
    rb_define_method(rb_cContinuation, "call", rb_cont_call, -1);
 
744
    rb_define_method(rb_cContinuation, "[]", rb_cont_call, -1);
 
745
    rb_define_global_function("callcc", rb_callcc, 0);
 
746
}
 
747
 
 
748
void
 
749
Init_Fiber_body(void)
 
750
{
 
751
    rb_define_singleton_method(rb_cFiber, "new", rb_fiber_s_new, 0);
 
752
    rb_define_method(rb_cFiber, "resume", rb_fiber_m_resume, -1);
 
753
    rb_define_method(rb_cFiber, "transfer", rb_fiber_m_transfer, -1);
575
754
    rb_define_method(rb_cFiber, "alive?", rb_fiber_alive_p, 0);
576
 
 
 
755
    rb_define_singleton_method(rb_cFiber, "yield", rb_fiber_s_yield, -1);
577
756
    rb_define_singleton_method(rb_cFiber, "current", rb_fiber_s_current, 0);
578
 
    rb_define_singleton_method(rb_cFiber, "prev", rb_fiber_s_prev, 0);
579
 
    rb_define_singleton_method(rb_cFiber, "yield", rb_fiber_s_yield, -1);
580
 
    rb_define_singleton_method(rb_cFiber, "new", rb_fiber_s_new, 0);
581
 
 
582
 
    rb_eFiberError = rb_define_class("FiberError", rb_eStandardError);
583
757
}
584