Waking ruby thread on external event

Discussion in 'Ruby' started by Bill Kelly, Mar 1, 2006.

  1. Bill Kelly

    Bill Kelly Guest

    Hi,

    I have Ruby embedded into a multithreaded C++ app. It's easy for
    a C++ thread to wait for an event from a Ruby thread.(*) But I'm
    looking for ways to allow a Ruby thread to sleep until an event
    from a C++ thread is posted.

    My application is cross-platform so my solution needs to work on
    Windows and OS X.

    So far all I can think of, without hacking ruby itself, is to
    open a TCP or UDP socket, and have the Ruby thread select() on
    the socket. Then the C++ side can fire a packet at the socket to
    wake the ruby thread up.

    Can anyone think of a simpler way? I haven't measured the overhead
    yet, but offhand it seems overkill to send a packet through the IP
    stack to do the work of a condition variable. (But yes I do need
    to actually measure it.)

    (*) Sleeping in C++ for an event from a Ruby thread: The C++ thread
    sleeps on a boost::condition variable. The Ruby thread invokes a C
    extension method which notify()'s the condition variable. Simple
    enough in this direction.


    Any thoughts appreciated,

    Thanks,

    Bill
    Bill Kelly, Mar 1, 2006
    #1
    1. Advertising

  2. Bill Kelly

    zdennis Guest

    Bill Kelly wrote:

    >
    > (*) Sleeping in C++ for an event from a Ruby thread: The C++ thread
    > sleeps on a boost::condition variable. The Ruby thread invokes a C
    > extension method which notify()'s the condition variable. Simple
    > enough in this direction.
    >
    >


    Can't you do this the other way around as well.... write C/C++ extension for ruby which stores
    reference to ruby thread, and call it from c++ code which would wake your ruby thread?

    Zach
    zdennis, Mar 1, 2006
    #2
    1. Advertising

  3. Bill Kelly wrote:
    > Hi,
    >
    > I have Ruby embedded into a multithreaded C++ app. It's easy for
    > a C++ thread to wait for an event from a Ruby thread.(*) But I'm
    > looking for ways to allow a Ruby thread to sleep until an event
    > from a C++ thread is posted.
    >
    > My application is cross-platform so my solution needs to work on
    > Windows and OS X.
    >
    > So far all I can think of, without hacking ruby itself, is to
    > open a TCP or UDP socket, and have the Ruby thread select() on
    > the socket. Then the C++ side can fire a packet at the socket to
    > wake the ruby thread up.
    >
    > Can anyone think of a simpler way? I haven't measured the overhead
    > yet, but offhand it seems overkill to send a packet through the IP
    > stack to do the work of a condition variable. (But yes I do need
    > to actually measure it.)


    Can the ruby thread just Thread.sleep, and wait for the C++ code to call
    rb_thread_wakeup() or whatever it is that implements Thread#wakeup ?

    --
    vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407
    Joel VanderWerf, Mar 1, 2006
    #3
  4. Bill Kelly

    Bill Kelly Guest

    From: "zdennis"
    >
    > Bill Kelly wrote:
    >>
    >> (*) Sleeping in C++ for an event from a Ruby thread: The C++ thread
    >> sleeps on a boost::condition variable. The Ruby thread invokes a C
    >> extension method which notify()'s the condition variable. Simple
    >> enough in this direction.
    >>

    >
    > Can't you do this the other way around as well.... write C/C++ extension
    > for ruby which stores reference to ruby thread, and call it from c++ code
    > which would wake your ruby thread?


    All ruby threads run on a single OS thread, and the ruby
    interpreter isn't generally reentrant, as I understand it.

    So I don't know how to put one ruby thread to sleep on something
    like a boost::condition variable without sleeping the whole OS
    thread ruby runs on, thus blocking all ruby threads.

    And I also don't know if I can call straight into ruby's eval.c
    from a non-ruby OS thread, to try to fiddle with the ruby threads
    and the ruby scheduler to wake my ruby thread up - due to the
    ruby interpreter not being reentrant. (Without hacking the ruby
    source code, at any rate.) Although if anyone knows to the
    contrary, that an external OS thread can safely wake up a
    ruby thread that'd be great.

    I may end up trying the UDP approach. It's got to be better
    than my initial make-it-work implementation, where my ruby
    threads sleep for 1/10 second and check a queue.

    But if anybody knows another way .... ? :)


    Regards,

    Bill
    Bill Kelly, Mar 1, 2006
    #4
  5. Bill Kelly

    Bill Kelly Guest

    From: "Joel VanderWerf" <>
    >
    > Can the ruby thread just Thread.sleep, and wait for the C++ code to call
    > rb_thread_wakeup() or whatever it is that implements Thread#wakeup ?


    Hi - somehow i'd not seen your reply. Thanks.

    Hmm...

    VALUE
    rb_thread_wakeup(thread)
    VALUE thread;
    {
    rb_thread_t th = rb_thread_check(thread);

    if (th->status == THREAD_KILLED)
    rb_raise(rb_eThreadError, "killed thread");
    rb_thread_ready(th);

    return thread;
    }

    I don't suppose this could be called from a different OS thread
    than ruby's.

    And the ruby interpreter may be waiting in a select() call when
    I need to wake up my ruby thread.

    Ah, well.. Maybe UDP is the way to go... <smile>


    Regards,

    Bill
    Bill Kelly, Mar 1, 2006
    #5
  6. Bill Kelly wrote:
    > From: "Joel VanderWerf" <>
    >>
    >> Can the ruby thread just Thread.sleep, and wait for the C++ code to call
    >> rb_thread_wakeup() or whatever it is that implements Thread#wakeup ?

    >
    > Hi - somehow i'd not seen your reply. Thanks.
    >
    > Hmm...
    >
    > VALUE
    > rb_thread_wakeup(thread)
    > VALUE thread;
    > {
    > rb_thread_t th = rb_thread_check(thread);
    >
    > if (th->status == THREAD_KILLED)
    > rb_raise(rb_eThreadError, "killed thread");
    > rb_thread_ready(th);
    >
    > return thread;
    > }
    >
    > I don't suppose this could be called from a different OS thread
    > than ruby's.


    Not necessarily such a problem. rb_thread_wakeup() doesn't muck around
    with any data structures that the thread scheduler uses. It just sets a
    couple of fields in the thread object. So there's a race condition, and
    a breaking of encapsulation, and a gnashing of teeth. But other than
    that, possible.

    > And the ruby interpreter may be waiting in a select() call when
    > I need to wake up my ruby thread.


    Oh. That's the real problem. You could keep one thread in a loop {sleep
    epsilon}, but that's back to square one.

    > Ah, well.. Maybe UDP is the way to go... <smile>


    Sounds like it is.

    --
    vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407
    Joel VanderWerf, Mar 1, 2006
    #6
    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. Wes Harrison

    Waking up sleeping Java applications

    Wes Harrison, Nov 29, 2003, in forum: Java
    Replies:
    29
    Views:
    908
  2. Scott Allen
    Replies:
    8
    Views:
    10,929
    Scott Allen
    May 2, 2004
  3. Vincenzo Piombo
    Replies:
    1
    Views:
    155
  4. Andreas Otto
    Replies:
    0
    Views:
    143
    Andreas Otto
    Oct 14, 2010
  5. Mellow Crow
    Replies:
    6
    Views:
    416
    Richard Cornford
    Nov 4, 2005
Loading...

Share This Page