cont.c.diff

oldmoe (Muhammad Ali), 12/27/2008 04:18 am

Download (4.9 kB)

cont.c (working copy)
570 570
/* fiber */
571 571
/*********/
572 572

  
573
/*
574
 *  Document-class: Fiber
575
 *
576
 *  Fibers are primitives for implementing light weight cooperative
577
 *  concurrency in Ruby. Basically they are a means of creating code blocks 
578
 *  that can be paused and resumed, much like threads. The main difference 
579
 *  is that they are never preempted and that the scheduling must be done by 
580
 *  the programmer and not the VM. 
581
 *
582
 *  As opposed to other stackless light weight concurrency models, each fiber
583
 *  comes with a small 4KB stack. This enables the fiber to be paused from deeply
584
 *  nested function calls within the fiber block.
585
 *
586
 *  When a fiber is created it will not run automatically. Rather it must be 
587
 *  be explicitly asked to run using the <code>Fiber#resume</code> method. 
588
 *  The code running inside the fibe can give up control by calling 
589
 *  <code>Fiber.yield</code> in which case it yields control back to caller 
590
 *  (the caller of the <code>Fiber#resume</code>).
591
 * 
592
 *  Upon yielding or termination the Fiber returns the value of the last 
593
 *  executed expression
594
 *  
595
 *  For instance:
596
 *  
597
 *    fiber = Fiber.new do
598
 *      Fiber.yield 1
599
 *      2
600
 *    end
601
 *
602
 *    puts fiber.resume
603
 *    puts fiber.resume
604
 *    puts fiber.resume
605
 *    
606
 *  <em>produces</em>
607
 *    
608
 *    1
609
 *    2
610
 *    FiberError: dead fiber called
611
 *     
612
 *  The <code>Fiber#resume</code> method accepts an arbitary number of
613
 *  parameters, if it is the first call to <code>resume</code> then they
614
 *  will be passed as block arguments. Other wise they will be the return
615
 *  value of the call to <code>Fiber.yield</code>
616
 *
617
 *  Example:
618
 *  
619
 *    fiber = Fiber.new do |first|
620
 *      second = Fiber.yield first + 2
621
 *    end
622
 *
623
 *    puts fiber.resume 10
624
 *    puts fiber.resume 14
625
 *    puts fiber.resume 18
626
 *
627
 *  <em>produces</em>
628
 *    
629
 *    12
630
 *    14
631
 *    FiberError: dead fiber called
632
 *
633
 */
634

  
573 635
#define FIBER_VM_STACK_SIZE (4 * 1024)
574 636

  
575 637
static VALUE
......
840 902
    return rb_fiber_transfer(return_fiber(), argc, argv);
841 903
}
842 904

  
905
/*
906
 *  call-seq:
907
 *     fiber.alive?
908
 *  
909
 *  Returns true if the fiber can still be resumed (or transferred to).
910
 *  After finishing execution of the fiber block this method will always
911
 *  return false.
912
 */
843 913
VALUE
844 914
rb_fiber_alive_p(VALUE fibval)
845 915
{
......
848 918
    return fib->status != TERMINATED;
849 919
}
850 920

  
921
/*
922
 *  call-seq:
923
 *     fiber.resume(args, ...)
924
 *  
925
 *  Resumes the fiber from the point at which the last <code>Fiber.yield</code>
926
 *  was called, or starts running it if it is the first call to 
927
 *  <code>resume</code>. Arguments passed to resume will be the value of
928
 *  the <code>Fiber.yield</code> expression or will be passed as block 
929
 *  parameters to the fiber's block if this is the first <code>resume</code>.
930
 *  
931
 *  Alternatively, when resume is called it evaluates to the arguments passed
932
 *  to the next <code>Fiber.yield</code> statement inside the fiber's block
933
 *  or to the block value if it runs to completion without any
934
 *  <code>Fiber.yield</code>
935
 */
851 936
static VALUE
852 937
rb_fiber_m_resume(int argc, VALUE *argv, VALUE fib)
853 938
{
854 939
    return rb_fiber_resume(fib, argc, argv);
855 940
}
856 941

  
942
/*
943
 *  call-seq:
944
 *     fiber.transfer(args, ...)
945
 *  
946
 *  Transfer control to another fiber, resuming it from where it last
947
 *  stopped or starting it if it was not resumed before. The calling 
948
 *  fiber will be suspended much like in a call to <code>Fiber.yield</code>.
949
 *  
950
 *  The fiber which recieves the transfer call is treats it much like 
951
 *  a resume call. Arguments passed to transfer are treated like those
952
 *  passed to resume.
953
 *     
954
 *  You cannot resume a fiber that transferred control to another one.
955
 *  This will cause a double resume error. You need to transfer control
956
 *  back to this fiber before it can yield and resume.
957
 */
857 958
static VALUE
858 959
rb_fiber_m_transfer(int argc, VALUE *argv, VALUE fib)
859 960
{
860 961
    return rb_fiber_transfer(fib, argc, argv);
861 962
}
862 963

  
964
/*
965
 *  call-seq:
966
 *     Fiber.yield(args, ...)
967
 *  
968
 *  Yields control back to the context that resumed the fiber, passing
969
 *  along any arguments that were passed to it. The fiber will resume
970
 *  processing at this point when <code>resume</code> is called next.
971
 *  Any arguments passed to the next <code>resume</code> will be the
972
 *  value that this <code>Fiber.yield</code> expression evaluates to.
973
 */
863 974
static VALUE
864 975
rb_fiber_s_yield(int argc, VALUE *argv, VALUE klass)
865 976
{
866 977
    return rb_fiber_yield(argc, argv);
867 978
}
868 979

  
980
/*
981
 *  call-seq:
982
 *     Fiber.current()
983
 *  
984
 *  Returns the current fiber. You need to <code>require 'fiber'</code>
985
 *  before using this method. If you are not running in the context of
986
 *  a fiber this method will return the root fiber.
987
 */
869 988
static VALUE
870 989
rb_fiber_s_current(VALUE klass)
871 990
{