On Thu, Jun 30, 2011 at 11:38:26AM +0100, Alan Conway wrote:
> >For any call that blocks on I/O (Session.synch :block => true) the Ruby
> >bindings can _not_ wrap that call in a Ruby thread and have it run while
> >the main application thread continues to run. So, even though we do
> >this:
> >
> >def sync(args = {},&callback)
> > block = args[:block] || false
> >
> > if block
> > # Spawn a thread to run the sync
> > Thread.new do
> > @session_impl.sync true
> > callback.call if callback
> > end
> > else
> > @sessimpl_impl.sync false
> > callback.call if callback
> > end
> >end
> >
> >the call to Session.sync will still block the whole application until
> >the call completes.
> >
>
> Not sure I follow here: if the call is blocking you _want_ the
> calling thread to be blocked till the call completes so what is
> wrong with:
I don't know that we want all threads to block. To my mind the goal is
we want to perform some action after the call finishes, some call which
depends on the blocking I/O completion before it can continue.
> def sync(args = {})
> block = args[:block] || false
> @session_impl.sync block
>
> Of course that doesn't allow you to have a callback invoked in
> non-blocking mode but C++ and python APIs don't currently support
> this either. When the underlying swigged API is improved to allow
> callbacks or futures for sync=false calls then that can be exposed
> in ruby.
>
> >In Ruby 1.9 we'll have other options to work with this since pthreads
> >will be available in the code. But, for now, we won't be able to use
> >_Ruby_ threads to work around this limitation.
> >
> >So in thinking this over, I see one of two paths to go down:
> >
> >1. Create a C++ child class of Session (and other classes that have
> >blocking I/O) and, when a blocking call is made, wrap the call in a
> >native thread. Then have the native code invoke the lamda funtion, and
> >make that lamda a requirement for such a call.
> >
> I would prefer to see the underlying API improved to provide
> callbacks or futures for non-blocking calls.
> Then a blocking call could be implemented as a non-blocking call to
> C++, plus ruby code to wait for the response without blocking the
> whole app. Not sure if/how the waiting and notification will work
> between pthreads in the C++ layer and ruby threads however.
I think even with the callback model we'll still need to handle threads
at some layer below the Ruby code.
> >2. Inform the developer that blocking calls will stop the application
> >until Ruby 1.9.
>
> Isn't that already the case with any blocking IO operation? So its
> something ruby developers are already living with.
Yeah. I was asked to try and solve this problem now, though. So I'm
trying to entertain all options for how we could overcome this blocking
behavior.
The way that seems to be the only path for this would be to put a layer
between the swigged APIs and the Ruby bindings I've written to add some
threading support only for blocking calls. The layer would take a
reference to a Proc object, start a native thread, and then invoke the
Proc object's callback when the thread completes.
> Agreed it is not a good thing but I think it's going to be difficult
> to solve this in Ruby until it is better solved in the underlying
> API and/or ruby gets pthreads.
That'll be the case in Ruby 1.9.
--
Darryl L. Pierce, Sr. Software Engineer @ Red Hat, Inc.
Delivering value year after year.
Red Hat ranks #1 in value among software vendors.
http://www.redhat.com/promo/vendor/
pgpUIThFrBcHZ.pgp
Description: PGP signature
