Forum: Ruby-Gnome 2 Programming multithreaded ruby app using GLib::Mainloop

Posted by Marcin Lewandowski (Guest)
on 2009-12-06 16:35
(Received via mailing list)
Hi,

I am programming a simple application that does two tasks in parallel.
First task is some sound processing using Ruby/GStreamer, while the 
second
one is monitoring STDIN for commands changing way how sounds got 
processed.

GStreamer uses GLib::Mainloop. I monitor STDIN using GLib::IOChannel, so 
it
also uses GLib::Mainloop.

How to make threading properly in this case? I need to interoperate 
between
two threads, with no lockdowns (it's a part of critical system). I mean
that when thread monitoring STDIN will receive some command it has to
change some parameters of Gst pipeline ASAP, and when there would be 
some
messages on the pipeline it should send them at STDOUT.

Thanks in advance,

m.
Posted by Mike Charlton (Guest)
on 2009-12-07 08:40
(Received via mailing list)
2009/12/7 Marcin Lewandowski <www@saepia.net>:
> I am programming a simple application that does two tasks in parallel.
> First task is some sound processing using Ruby/GStreamer, while the second
> one is monitoring STDIN for commands changing way how sounds got processed.

I don't understand why this needs to be done in two threads.  As you 
say:

> GStreamer uses GLib::Mainloop. I monitor STDIN using GLib::IOChannel, so it
> also uses GLib::Mainloop.

Remember that your computer doesn't actually do things in parallel.  It
allocates a little bit of time for one thread, works on it and then goes
to another thread. But here you have GLib::Mainloop doing that for you.
It will work on GStreamer stuff when it has it and will work on your
IO when events come in.

No matter what you do (even if you use threads) one thing will
pause for a small amount of time while the other thing is happening.
If you use a thread, you have no control over when that pause
happens.  It is almost always better to use something like GLib:Mainloop
because you have control over the amount of processing that
happens.  If you are familiar with design patterns, this is known
as a reactor pattern.

I don't know exactly what you are doing, but I guess you want
to do some long term processing with GStreamer and also
handle IO at the same time.  If that's the case, break down
your processing in GStreamer into parts. Have Mainloop
call your GStreamer processing and do one small part
and then return.  Repeat as necessary.  You may have to create
an object that holds the state of your processing so that
it knows where to start up from.  Since you say GStreamer
is already integrated into Mainloop, I suppose this
should usually happen without you needing to do much (???).
At worst you may have to create a new GSource to
handle your processing.

I'm afraid I'm not familiar with either GStreamer, nor IOChannel, so
I can't really help on the specifics.  But I hope I'm pointing you
in the right direction.  I suspect that if you try to use a thread
it will never work properly.  If I have misunderstood what you were
asking, please forgive me :-)

        MikeC
Posted by Marcin Lewandowski (Guest)
on 2009-12-07 21:36
(Received via mailing list)
Thanks for your answer.

Well I thought that Gst would handle that task changing automatically, 
but
as I can see both IOChannel and Gst are blocking.

Is there any pretty way to implement what you have proposed? It's 
exactly
what I need, but I don't know the syntax.

m.
Posted by Mike Charlton (Guest)
on 2009-12-08 09:06
(Received via mailing list)
2009/12/8 Marcin Lewandowski <www@saepia.net>:
> Well I thought that Gst would handle that task changing automatically, but
> as I can see both IOChannel and Gst are blocking.

Hmmm... Well, I'm not sure what methods you're using, but
I guess in IOChannel, for instance, you are using each_char(), etc.
You have to use add_watch() instead.  For example:

add_watch(GLib::IOChannel::IN) do |channel, condition|
    string = channel.read()
    # parse the string here and do your output or whatever
end

Or instead of read() you can use readline() or readchar() until
you catch the EOF exception.

I'm not at all familiar with Gst, but looking at the tutorial
it seems that the Bin::iterate() is what you want to call
when you want to process incoming events (usually from
the Pipeline).

And I notice from a previous posting of yours that
you already know how to add a watch from the bus
(which doesn't seem to be documented anywhere???)

But it seems that your problem is that you are
calling mainloop.run and mainloop.stop.  Instead, just
run iterate() on the pipeline everytime you get
an event.  That should fix your problem.  I hope :-)
Like I said, I'm not familiar with these libraries.
Hopefully someone who is will chime in (or maybe
you're becoming the expert in the are ;-) )

           MikeC
Posted by Simon Arnaud (Guest)
on 2009-12-08 11:24
(Received via mailing list)
Hi

I don't have a solution to your problem. I mostly wanted to react to :

2009/12/7 Mike Charlton <mikekchar@gmail.com>

> Remember that your computer doesn't actually do things in parallel.  It
> allocates a little bit of time for one thread, works on it and then goes
> to another thread.
>

While this is true for a mono CPU computer, it might not be for dual or
more.
Moreover, his situation is quite particular. The thread waiting for IO 
is
mostly sleeping.

I agree though, that using GLib wake up mechanisms would be better in 
this
case, than threading. However, if you need to react in 'realtime', and 
not
'very fast', GLib might not be the right library.

Sorry, I'm not really helpfull.

Simon
Posted by Marcin Lewandowski (Guest)
on 2009-12-08 16:17
(Received via mailing list)
> add_watch(GLib::IOChannel::IN) do |channel, condition|
>     string = channel.read()
>     # parse the string here and do your output or whatever
> end

Yes, I've did that already. And it's blocking.

iterate doesn't exist any more in Gst

m.
Please log in before posting. Registration is free and takes only a minute.
Existing account (Switch to SSL-encrypted connection)
NEW: Do you have a Google/GoogleMail or Yahoo account? No registration required!
Log in with Google account | Log in with Yahoo account
No account? Register here.