Thread safety: Serializing access to ruby interpreter- again

Ask a Question related to Ruby, Design and Development.

  1. #1

    Default Thread safety: Serializing access to ruby interpreter- again

    I recently asked about this and got answers, but here I go again:

    How can I efficiently serialize access to the ruby interpreter. I have to
    make sure all access to the ruby interpreter happens on a particular thread
    (not a ruby thread, mind you), so when a different thread attempts to access
    the ruby interpreter I need it to have it post the job to a queue and then
    wait for a ruby worker thread on the ruby-thread (:-)) to execute whatever
    it needs done. Btw, in this mail I use the term ruby-thread, with a dash in
    the middle, as a reference to the heavy-weight thread in which the ruby
    interpreter executes.

    The thing is that if I have a ruby thread on the ruby-thread block on a
    heavyweight thread lock the entire ruby-thread is blocked. This is
    demonstrated by this bit below (which requires my dotnet module to work). It
    simply starts a thread that writes to the console continuously and then the
    main thread waits for a signal on anObject. However that wait() call blocks
    the entire ruby-thread not just the "green" ruby main thread, so I never get
    to see a steady stream of hello worlds, and that is what ruins my day.

    require 'dotnet'

    t = Thread.new { while true; sleep 0.1; puts "hello world"; end }

    anObject = System::EventArgs.new

    System::Threading::Monitor.enter(anObject)
    System::Threading::Monitor.wait(anObject) # This blocks the entire
    ruby-thread
    System::Threading::Monitor.exit(anObject)

    t.join


    So if I am not allowed to touch the ruby interpreter from other threads than
    the ruby-thread how can I wake up a sleeping worker thread when there is
    something for it to do?

    Is there a heavyweight-thread-safe way to wake up a ruby thread? Shouldn't
    there be?

    - Thomas


    Thomas Sondergaard Guest

  2. Similar Questions and Discussions

    1. Thread safety/synchronization?
      Flex/AS doesn't appear to have any overt synchronization mechanism, is it handled under the covers (ie is every method synchronized?) or is it user...
    2. apartmant thread safety
      I'm rather confused about this whole threading business of IIS, ASP and COM components. We have an apartment threaded component with a function...
    3. Trying to figure out thread safety
      (Having been told of a solution to one problem (File::CREAT was indeed what was needed), I'll now go off on something entirely different.) I've...
    4. Ruby interpreter thread safety
      I have a scenario where a ruby extension module starts real/os/heavy-weight threads that may call back to ruby. As far as I understand the ruby...
    5. Thread safety of vm_copy
      I tried looking around for explicit documentation on this but to no avail, perhaps it is too basic. On Mac OS X the Mach function vm_copy has a...
  3. #2

    Default Re: Thread safety: Serializing access to ruby interpreter- again

    Hi,

    At Thu, 18 Sep 2003 09:32:21 +0900,
    Thomas Sondergaard wrote:
    > So if I am not allowed to touch the ruby interpreter from other threads than
    > the ruby-thread how can I wake up a sleeping worker thread when there is
    > something for it to do?
    Using a pipe (or any IO) as the trigger which wakes Monitor up.
    > Is there a heavyweight-thread-safe way to wake up a ruby thread? Shouldn't
    > there be?
    Agree, but wait until 1.9 or perhaps 2.0.

    --
    Nobu Nakada

    nobu.nokada@softhome.net Guest

  4. #3

    Default Re: Thread safety: Serializing access to ruby interpreter- again

    Hi Nobu,
    > Using a pipe (or any IO) as the trigger which wakes Monitor up.
    That doesn't work. Blocking on a pipe (or any IO) in Windows blocks the
    entire ruby process. This sample will just block and get no where in Windows
    after writing "hello from main" once, while in Linux it happily prints
    "hello from main" once a second.

    readPipe, writePipe = IO.pipe

    t = Thread.new { while true; sleep 1; puts "got #{readPipe.readline}"; end }

    while true
    sleep 1
    puts "hello from main"
    end

    t.join


    Out of curiousity, why does this happen on Windows? Is it not fixable?

    Tom


    Thomas Sondergaard Guest

  5. #4

    Default Re: Thread safety: Serializing access to ruby interpreter- again

    Hi,

    At Fri, 19 Sep 2003 17:37:09 +0900,
    Thomas Sondergaard wrote:
    > > Using a pipe (or any IO) as the trigger which wakes Monitor up.
    >
    > That doesn't work. Blocking on a pipe (or any IO) in Windows blocks the
    > entire ruby process. This sample will just block and get no where in Windows
    > after writing "hello from main" once, while in Linux it happily prints
    > "hello from main" once a second.
    Socket might work.
    > Out of curiousity, why does this happen on Windows? Is it not fixable?
    Because winsock's select() supports only socket handles.

    --
    Nobu Nakada

    nobu.nokada@softhome.net Guest

  6. #5

    Default Re: Thread safety: Serializing access to ruby interpreter- again

    > Socket might work.
    If you say so, I'll give it a try.
    > > Out of curiousity, why does this happen on Windows? Is it not fixable?
    >
    > Because winsock's select() supports only socket handles.
    Is all ruby IO implemented in terms of select to avoid blocking the process?
    Why doesn't select block the process, btw?

    Thomas


    Thomas Sondergaard Guest

  7. #6

    Default Re: Thread safety: Serializing access to ruby interpreter- again

    On Wed, 2003-09-24 at 21:38, Thomas Sondergaard wrote:
    > > Socket might work.
    >
    > If you say so, I'll give it a try.
    >
    > > > Out of curiousity, why does this happen on Windows? Is it not fixable?
    > >
    > > Because winsock's select() supports only socket handles.
    >
    > Is all ruby IO implemented in terms of select to avoid blocking the process?
    > Why doesn't select block the process, btw?
    >
    > Thomas
    Well, I'm a newbie to Ruby, but unfortunately old enough to remember
    writing C code before real threads existed.

    I'm guessing Ruby threads work in the old "cooperative" manner, as
    follows:

    What you would do is replace blocking calls to read operations with
    calls to functions implemented like this:

    read_from_socket:

    for(;;) {
    check for data available
    if data is available
    read data and return it
    else
    schedule some other thread to run // aka "yield"
    }

    The check for data is done with a NON-BLOCKING select call, ie one that
    returns immediately even if no data is currently available. In that
    case, the current "thread" stops running and some other "thread" gets
    the CPU. Eventually the current "thread" is rescheduled, goes back to
    the top of the loop, and checks for data again.

    It was always a pain to code this way, because you had to call these
    "yielding" versions of standard library calls rather than the real ones,
    for every library function that might block.

    However given that languages like Ruby always have "glue" code for
    calling native operations like read & write, it works quite tidily for
    them.

    The disadvantage, of course, is that because all threading is
    implemented within a single real OS thread, the app can't take advantage
    of systems which really have multiple CPUs. And thread "pre-emption" is
    a bit flaky.

    I am guessing that Windows doesn't provide a way to check a socket for
    the presence of data without blocking, meaning that this just can't be
    implemented.

    Cheers,

    Simon


    Simon Kitching Guest

Posting Permissions

  • You may not post new threads
  • You may post replies
  • You may not post attachments
  • You may not edit your posts

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139