Programming multithreaded ruby app using GLib::Mainloop

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.

2009/12/7 Marcin L. [email protected]:

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 :slight_smile:

    MikeC

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.

Hi

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

2009/12/7 Mike C. [email protected]

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

2009/12/8 Marcin L. [email protected]:

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 :slight_smile:
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 :wink: )

       MikeC

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.