pulling my hair out, why won't Kernel.sleep(0) sleep?

Discussion in 'Ruby' started by Sam Roberts, Feb 18, 2005.

  1. Sam Roberts

    Sam Roberts Guest

    Can anybody give me any hints as to what I should be looking for? What
    can cause sleep(0) to wake up?

    I've got a thread that does

    loop do
    sleep(delay)

    ... do stuff, then set delay to 0 because there is no more work ...

    delay = 0
    end


    And my loop is busy looping, sleep just won't!

    Whether it does or not is triggered by changes in what appear to me to
    be completely unrelated code. I'm mystified.

    Thanks,
    Sam
     
    Sam Roberts, Feb 18, 2005
    #1
    1. Advertising

  2. Sam Roberts

    Assaph Mehr Guest

    Sam Roberts wrote:
    > Can anybody give me any hints as to what I should be looking for?

    What
    > can cause sleep(0) to wake up?
    >
    > I've got a thread that does
    >
    > loop do
    > sleep(delay)
    >
    > ... do stuff, then set delay to 0 because there is no more work

    ....
    >
    > delay = 0
    > end
    >
    >
    > And my loop is busy looping, sleep just won't!
    >
    > Whether it does or not is triggered by changes in what appear to me

    to
    > be completely unrelated code. I'm mystified.


    Silly question: Is there another thread active at the same time? I
    don't think a thread can sleep if it's the only one...
     
    Assaph Mehr, Feb 18, 2005
    #2
    1. Advertising

  3. Sam Roberts

    Luke Graham Guest

    From the docs - SIGALRM or another thread calling run. If these cases
    arent relevant, could you post an example of the unrelated code?


    On Fri, 18 Feb 2005 12:16:41 +0900, Sam Roberts <> wrote:
    > Can anybody give me any hints as to what I should be looking for? What
    > can cause sleep(0) to wake up?
    >
    > I've got a thread that does
    >
    > loop do
    > sleep(delay)
    >
    > ... do stuff, then set delay to 0 because there is no more work ...
    >
    > delay = 0
    > end
    >
    > And my loop is busy looping, sleep just won't!
    >
    > Whether it does or not is triggered by changes in what appear to me to
    > be completely unrelated code. I'm mystified.
    >
    > Thanks,
    > Sam
    >
    >



    --
    spooq
     
    Luke Graham, Feb 18, 2005
    #3
  4. Sam Roberts <> wrote:
    > Can anybody give me any hints as to what I should be looking for? What
    > can cause sleep(0) to wake up?


    The documentation is wrong.

    sleep(0) returns immediately. sleep with *zero* arguments sleeps
    forever.

    static VALUE
    rb_f_sleep(argc, argv)
    int argc;
    VALUE *argv;
    {
    int beg, end;

    beg = time(0);
    if (argc == 0) {
    rb_thread_sleep_forever();
    }
    else if (argc == 1) {
    rb_thread_wait_for(rb_time_interval(argv[0]));
    }
    else {
    rb_raise(rb_eArgError, "wrong number of arguments");
    }

    end = time(0) - beg;

    return INT2FIX(end);
    }

    Cheers,
    Navin.
     
    Navindra Umanee, Feb 18, 2005
    #4
  5. Assaph Mehr wrote:

    > Silly question: Is there another thread active at the same time? I
    > don't think a thread can sleep if it's the only one...


    Huh? You mean the main thread cannot sleep? Or have I mis-read your answer?

    -- shanko
     
    Shashank Date, Feb 18, 2005
    #5
  6. Sam Roberts

    Assaph Mehr Guest

    Shashank Date wrote:
    > Assaph Mehr wrote:
    >
    > > Silly question: Is there another thread active at the same time? I
    > > don't think a thread can sleep if it's the only one...

    >
    > Huh? You mean the main thread cannot sleep? Or have I mis-read your

    answer?

    Perhaps I wasn't clear. The main thread can of course sleep for a
    specified period. But if you do a sleep 0, it means sleep until woken
    up. Ruby will check, see that there is no other thread waiting and will
    thus wake the main thread again.
    So if you only have one thread, you can't sleep indefinitely.

    Assaph
     
    Assaph Mehr, Feb 18, 2005
    #6
  7. Sam Roberts

    Assaph Mehr Guest

    Assaph Mehr wrote:
    > Shashank Date wrote:
    > > Assaph Mehr wrote:
    > >
    > > > Silly question: Is there another thread active at the same time?

    I
    > > > don't think a thread can sleep if it's the only one...

    > >
    > > Huh? You mean the main thread cannot sleep? Or have I mis-read your

    > answer?
    >
    > Perhaps I wasn't clear. The main thread can of course sleep for a
    > specified period. But if you do a sleep 0, it means sleep until woken
    > up. Ruby will check, see that there is no other thread waiting and

    will
    > thus wake the main thread again.
    > So if you only have one thread, you can't sleep indefinitely.


    Oops, looks like I was wrong. See Navindra's clarification.
     
    Assaph Mehr, Feb 18, 2005
    #7
  8. Sam Roberts

    Sam Roberts Guest

    Quoteing , on Fri, Feb 18, 2005 at 12:33:13PM +0900:
    > Sam Roberts <> wrote:
    > > Can anybody give me any hints as to what I should be looking for? What
    > > can cause sleep(0) to wake up?

    >
    > The documentation is wrong.
    >
    > sleep(0) returns immediately. sleep with *zero* arguments sleeps
    > forever.


    Thank you, thank you, thank you!

    I had started to notice that sometimes the code busy loops, and
    sometimes it doesn't, it doesn't matter whether I make any code changes,
    that turned out to be unrelated.

    Do you have any idea why this should be? What does Kernel.sleep(0)
    actually do?

    Sam

    >
    > static VALUE
    > rb_f_sleep(argc, argv)
    > int argc;
    > VALUE *argv;
    > {
    > int beg, end;
    >
    > beg = time(0);
    > if (argc == 0) {
    > rb_thread_sleep_forever();
    > }
    > else if (argc == 1) {
    > rb_thread_wait_for(rb_time_interval(argv[0]));
    > }
    > else {
    > rb_raise(rb_eArgError, "wrong number of arguments");
    > }
    >
    > end = time(0) - beg;
    >
    > return INT2FIX(end);
    > }
    >
    > Cheers,
    > Navin.
    >
     
    Sam Roberts, Feb 18, 2005
    #8
  9. Sam Roberts <> wrote:
    > I had started to notice that sometimes the code busy loops, and
    > sometimes it doesn't, it doesn't matter whether I make any code changes,
    > that turned out to be unrelated.
    >
    > Do you have any idea why this should be? What does Kernel.sleep(0)
    > actually do?


    I would guess that the sleep is triggering the thread scheduler to
    check the queue for eligible threads to run. Probably sometimes the
    same thread is chosen and sometimes another thread.

    Not 100% sure.

    Cheers,
    Navin.
     
    Navindra Umanee, Feb 18, 2005
    #9
  10. Hi,

    In message "Re: pulling my hair out, why won't Kernel.sleep(0) sleep?"
    on Fri, 18 Feb 2005 13:07:28 +0900, Sam Roberts <> writes:

    |> The documentation is wrong.

    Oops. I will fix.

    |I had started to notice that sometimes the code busy loops, and
    |sometimes it doesn't, it doesn't matter whether I make any code changes,
    |that turned out to be unrelated.
    |
    |Do you have any idea why this should be? What does Kernel.sleep(0)
    |actually do?

    I guess it was busy looping, but there were other threads to work
    sometimes. sleep(0) does not sleep but causes context switch.

    matz.
     
    Yukihiro Matsumoto, Feb 18, 2005
    #10
  11. Sam Roberts

    Pit Capitain Guest

    Sam Roberts schrieb:
    > I had started to notice that sometimes the code busy loops, and
    > sometimes it doesn't, it doesn't matter whether I make any code changes,
    > that turned out to be unrelated.
    >
    > Do you have any idea why this should be?


    Could it be that the delay variable is shared between the threads?

    Regards,
    Pit
     
    Pit Capitain, Feb 18, 2005
    #11
  12. Sam Roberts

    Sam Roberts Guest

    Quoteing , on Fri, Feb 18, 2005 at 01:50:26PM +0900:
    > Hi,
    >


    > |Do you have any idea why this should be? What does Kernel.sleep(0)
    > |actually do?
    >
    > I guess it was busy looping, but there were other threads to work
    > sometimes. sleep(0) does not sleep but causes context switch.


    That describes what I saw, kindof (race conditions are inherently
    weird).

    Thanks,
    Sam

    Here's a start to the docs, but I don't know if my description is
    correct!

    /*
    * call-seq:
    - * sleep(duration=0) => fixnum
    + * sleep(duration) => fixnum
    + * sleep() => fixnum
    *
    - * Suspends the current thread for _duration_ seconds (which may be
    - * any number, including a +Float+ with fractional seconds). Returns the actual
    - * number of seconds slept (rounded), which may be less than that asked
    - * for if the thread was interrupted by a +SIGALRM+, or if
    - * another thread calls <code>Thread#run</code>. An argument of zero
    - * causes +sleep+ to sleep forever.
    - *
    + * Suspends the current thread for _duration_ seconds (which may be any
    + * number, including a +Float+ with fractional seconds). Calling sleep with
    + * no arguments causes +sleep+ to sleep "forever" - where "forever" means
    + * until it is woken up, see below. Calling sleep with an argument of
    + * +0+ causes a context switch, if another thread is ready to be
    + * scheduled.
    + *
    + * Returns the actual number of seconds slept (rounded), which may be less
    + * than that asked for if the thread was interrupted by a +SIGALRM+, or if
    + * another thread calls <code>Thread#run</code>.
    + *
    + * WHAT ABOUT OTHER SIGNALS?
    + *
    * Time.new #=> Wed Apr 09 08:56:32 CDT 2003
    * sleep 1.2 #=> 1
    * Time.new #=> Wed Apr 09 08:56:33 CDT 2003
     
    Sam Roberts, Feb 18, 2005
    #12
  13. Navindra Umanee wrote:
    > Sam Roberts <> wrote:
    > > Can anybody give me any hints as to what I should be looking for?

    What
    > > can cause sleep(0) to wake up?

    >
    > The documentation is wrong.
    >
    > sleep(0) returns immediately. sleep with *zero* arguments sleeps
    > forever.
    >
    > static VALUE
    > rb_f_sleep(argc, argv)
    > int argc;
    > VALUE *argv;
    > {
    > int beg, end;
    >
    > beg = time(0);
    > if (argc == 0) {
    > rb_thread_sleep_forever();
    > }
    > else if (argc == 1) {
    > rb_thread_wait_for(rb_time_interval(argv[0]));
    > }
    > else {
    > rb_raise(rb_eArgError, "wrong number of arguments");
    > }
    >
    > end = time(0) - beg;
    >
    > return INT2FIX(end);
    > }
    >
    > Cheers,
    > Navin.


    Why are arguments being counted manually? It's less code, less error
    prone, and doesn't force you to explicitly raise an ArgumentError if
    the argument count is wrong.

    Refactored:

    /*
    * :call-seq:
    * sleep(numeric=nil)
    *
    * Suspends the current thread for +numeric+ seconds (which may be a
    * Float with fractional seconds. Returns the actual number of seconds
    * slept, rounded, which may be less than what was asked for if the
    * thread was interrupted by a SIGALARM or if another thread calls
    * Thread#run.
    *
    * If no argument is provided then it will sleep forever.
    */
    static VALUE
    rb_f_sleep(argc, argv)
    int argc;
    VALUE *argv;
    {
    int beg, end;
    VALUE rbNum;

    beg = time(0);

    rb_scan_args(argc,argv,"01",&rbNum);

    if(NIL_P(rbNum)){
    rb_thread_sleep_forever();
    }
    else{
    rb_thread_wait_for(rb_time_interval(rbNum));
    }

    end = time(0) - beg;

    return INT2FIX(end);
    }
     
    Daniel Berger, Feb 18, 2005
    #13
  14. Sam Roberts

    ts Guest

    >>>>> "D" == Daniel Berger <> writes:

    D> Why are arguments being counted manually?

    it's faster :)

    D> if(NIL_P(rbNum)){
    D> rb_thread_sleep_forever();
    D> }

    it don't do the same thing :)

    uln% ruby -e 'sleep(nil)'
    -e:1:in `sleep': can't convert NilClass into time interval (TypeError)
    from -e:1
    uln%



    Guy Decoux
     
    ts, Feb 18, 2005
    #14
  15. ts wrote:
    > >>>>> "D" == Daniel Berger <> writes:

    >
    > D> Why are arguments being counted manually?
    >
    > it's faster :)
    >
    > D> if(NIL_P(rbNum)){
    > D> rb_thread_sleep_forever();
    > D> }
    >
    > it don't do the same thing :)
    >
    > uln% ruby -e 'sleep(nil)'
    > -e:1:in `sleep': can't convert NilClass into time interval

    (TypeError)
    > from -e:1
    > uln%


    I'm confused - what conversion is it trying to do? I thought these two
    were equivalent:

    if(NIL_P(rbNum))

    if(Qnil == rbNum)

    No?

    Regards,

    Dan
     
    Daniel Berger, Feb 18, 2005
    #15
  16. Sam Roberts

    ts Guest

    >>>>> "D" == Daniel Berger <> writes:

    D> I'm confused - what conversion is it trying to do? I thought these two
    D> were equivalent:

    D> if(NIL_P(rbNum))

    D> if(Qnil == rbNum)

    if you want to write the same with rb_scan_args(), you must write

    if (rb_scan_args(argc, argv, "01", &rbNum)) {
    rb_thread_wait_for(rb_time_interval(rbNum));
    }
    else {
    rb_thread_sleep_forever();
    }


    and you see that the ruby version is faster :)


    Guy Decoux
     
    ts, Feb 18, 2005
    #16
  17. Using rb_scan_args vs counting argc (was: pulling my hair out, why won't Kernel.sleep(0) sleep?)

    ts wrote:
    > >>>>> "D" == Daniel Berger <> writes:

    >
    > D> I'm confused - what conversion is it trying to do? I thought

    these two
    > D> were equivalent:
    >
    > D> if(NIL_P(rbNum))
    >
    > D> if(Qnil == rbNum)
    >
    > if you want to write the same with rb_scan_args(), you must write
    >
    > if (rb_scan_args(argc, argv, "01", &rbNum)) {
    > rb_thread_wait_for(rb_time_interval(rbNum));
    > }
    > else {
    > rb_thread_sleep_forever();
    > }
    >
    >
    > and you see that the ruby version is faster :)
    >
    >
    > Guy Decoux


    First things first. You're skirting the issue. It SHOULD work. There
    is some sort of side effect happening, because the error is NOT coming
    from process.c. I added some debug print statements directly into
    process.c and rebuilt. I can't even get to that point before the error
    is raised. This smells like a bug and/or some kind of global setting
    being used some where.

    Second, counting argc is not significantly faster than using
    rb_scan_args(). Using the following code, counting argc was faster by
    by .01 to .05 seconds over *ONE MILLION* iterations. That's 5.0e-008
    per iteration. Rather insignificant don't you think?

    /* foo.c
    *
    * The purpose of this class is to test the speed of manual counting
    * of argc vs using rb_scan_args().
    */
    #include "ruby.h"
    #include <stdlib.h>

    VALUE some_func(int num);
    int other_func(VALUE rbNum);

    VALUE some_func(int num){
    VALUE rbNum = INT2FIX(num);
    return rbNum;
    }

    int other_func(VALUE rbNum){
    int y = FIX2INT(rbNum);
    return y;
    }

    static VALUE test_scan(int argc, VALUE* argv){
    VALUE rbNum;

    rb_scan_args(argc,argv,"01",&rbNum);

    if(NIL_P(rbNum)){
    some_func(55);
    }
    else{
    other_func(argv[0]);
    }

    return rbNum;
    }

    static VALUE test_count(int argc, VALUE* argv){
    if(argc == 0){
    some_func(55);
    }
    else if(argc == 1){
    other_func(argv[0]);
    }
    else{
    rb_raise(rb_eStandardError,"Wrong number of arguments");
    }

    return Qnil;
    }

    void Init_foo(){
    VALUE cFoo = rb_define_class("Foo",rb_cObject);
    rb_define_singleton_method(cFoo,"test_scan",test_scan,-1);
    rb_define_singleton_method(cFoo,"test_count",test_count,-1);
    }

    # extconf.rb
    require "mkmf"
    create_makefile("foo")

    # test_basic.rb
    # Proof that you ought to be able to send 'nil'
    # Adding debug print statements to the C code proves that it
    # does what I intend.

    $:.unshift Dir.pwd

    require "foo"

    Foo.test_scan(5) # works
    Foo.test_scan # works
    Foo.test_scan(nil) # works (!)

    # test_speed.rb
    $LOAD_PATH.unshift Dir.pwd

    require "foo"
    require "benchmark"
    include Benchmark

    bm do |x|
    x.report("scan"){
    1000000.times{ Foo.test_scan }
    }
    x.report("count"){
    1000000.times{ Foo.test_count }
    }
    end

    Results of benchmark using on Solaris 9, gcc 3.4.2, 500Mhz Sparc Ultra
    IIe, 512 MB RAM:

    user system total real
    scan 3.220000 0.000000 3.220000 (3.224927)
    count 3.170000 0.000000 3.170000 (3.179761)

    Regards,

    Dan
     
    Daniel Berger, Feb 18, 2005
    #17
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Replies:
    9
    Views:
    456
    Toby A Inkster
    Jul 16, 2003
  2. Richard
    Replies:
    6
    Views:
    338
    Richard
    Nov 15, 2003
  3. Mr. SweatyFinger
    Replies:
    2
    Views:
    2,030
    Smokey Grindel
    Dec 2, 2006
  4. yogesh
    Replies:
    3
    Views:
    591
    Kenny McCormack
    Feb 12, 2006
  5. Mr. Politics

    Pulling my hair out..

    Mr. Politics, Feb 12, 2007, in forum: C++
    Replies:
    9
    Views:
    465
Loading...

Share This Page