[patch] Do state calls in a seperate thread

Hi,

See patch for details. I’ve attached a little test-case to show the
effect of
this patch. The test-case just switches a simple pipeline with a
handoff
callback from an identity to playing and back to stop 10 times…
Without this
patch it never succeeds to actually do 10 ten state changes, but
instead
deadlocks trying to stop the pipeline.

Note that this is ofcourse a race condition, so depending on you
machine this
might happen more or less often. On my SMP machine it never seems to
complete
more then three changes without the patch.

I didn’t know where to put this test-case in the source tree so i
attached it
seperately

Sjoerd

Hi,

In [email protected]
“[ruby-gnome2-devel-en] [patch] Do state calls in a seperate thread”
on Sat, 29 Mar 2008 18:42:32 +0100,
Sjoerd S. [email protected] wrote:

See patch for details.

It was very happy for us if you considered to follow our
coding-style.

Can we use GAsyncQueue instead of pipe()? We use it in
glib/src/rbgutil_callback.c.

* src/rbgst-element.c: Remove stopped?,ready?, paused?, playing? and wait as
  these aren't thread-safe. The get_state functions should be used to get
  states and/or wait for state changes

Should we remove them? Are they useful?

                     I've attached a little test-case to show the effect of

this patch. The test-case just switches a simple pipeline with a handoff
callback from an identity to playing and back to stop 10 times… Without this
patch it never succeeds to actually do 10 ten state changes, but instead
deadlocks trying to stop the pipeline.

Thanks. It’s confirmed on my environment too.

I didn’t know where to put this test-case in the source tree so i attached it
seperately

Use under test/.

Hi,

And use RVAL2XXX not RGST_XXX.

In [email protected]
“Re: [ruby-gnome2-devel-en] [patch] Do state calls in a seperate
thread” on Sun, 30 Mar 2008 08:40:19 +0900 (JST),
Kouhei S. [email protected] wrote:

  states and/or wait for state changes

I didn’t know where to put this test-case in the source tree so i attached it
seperately

Use under test/.

Thanks,

kou

On Sun, Mar 30, 2008 at 08:40:19AM +0900, Kouhei S. wrote:

Can we use GAsyncQueue instead of pipe()? We use it in
glib/src/rbgutil_callback.c.

Incidentally i was just reading that code as i hit a deadlock in one of
my
non-trivial examples… Unfortunately the code has several issues. In
invoke_callback_in_ruby_thread it uses various rb_ functions. As ruby
isn’t
thread-safe and invoke_callback_in_ruby_thread is run from another
thread this
is a bit troublesome.

And apart from that rb_thread_wakeup (which one shouldn’t use in a
non-ruby
thread in the first place) only sets some flags on the thread, it
doesn’t
actually wake up the thread. So the thread only gets run if
rb_thread_schedule
is called in the ruby thread, which might take a very long time (maybe
forever).

So these things need to be fixed and then i can probably convert the
gstreamer
functions to something similar. For now the best plan i’ve come up with
is to
call IO.pipe from C and use the filedescriptors that creates in a
similar way
we used those of pipe() before the conversion.

* src/rbgst-element.c: Remove stopped?,ready?, paused?, playing? and
wait as these aren't thread-safe. The get_state functions should be
used to get states and/or wait for state changes

Should we remove them? Are they useful?

They are not really usefull… You can get the same information from
get_state
and more importantly they don’t take into account that while calling
this
function the underlying state might already have changed.

Use under test/.

Will do

Sjoerd

Wernher von Braun settled for a V-2 when he coulda had a V-8.

On Sun, Mar 30, 2008 at 04:22:06PM +0900, Kouhei S. wrote:

non-trivial examples… Unfortunately the code has several issues. In
Could you show the non-trivial example?
I could, it’s the video-player from ruby-gstreamer0.10, but to get that
working
serveral outstanding patches of mine are still needed. So not that
usefull at
this point. Luckily given the analysis above it’s quite easy to make a
trivial
example (attached). I’ll clean it up a bit later and throw it in the
test dir
for automated testing. (Btw, there is both tests and test at this
point, can
we get rid of one to prevent confusion?)

Anyway what the attached patch does is to create a pipeline with a
videtestsrc
that behaves as a live source and with an fps of 2. All the buffers
going
through the pipeline are handed of to a callback which prints a
timestamp. So
what you would expect is to have two lines printed every second. But
the catch
is the program in the ruby thread first calls sleep(1) five times and
then
calls sleep(5). Resulting in an output similar to:

Sleeping 5 times for one seconds
Sun Mar 30 12:25:48 +0200 2008: got buffer
Sun Mar 30 12:25:49 +0200 2008: got buffer
Sun Mar 30 12:25:49 +0200 2008: got buffer
Sun Mar 30 12:25:50 +0200 2008: got buffer
Sun Mar 30 12:25:51 +0200 2008: got buffer
Sun Mar 30 12:25:52 +0200 2008: got buffer
Sun Mar 30 12:25:52 +0200 2008: got buffer
Sleeping for five seconds
Sun Mar 30 12:25:57 +0200 2008: got buffer
done

Which shows the effect of not having the ruby thread callback scheduled
when
needed… If instead of sleeping the ruby thread is purely waiting on an
even
that might depends on the callback actually being executed, then you’ll
get a
deadlock :frowning:

instead of element.playing??
element.get_state(0)[1] would be the equivalent of playing? (get_state
blocks
untill there is a state changes or its timeout expires)…

But that code would most likely be wrong. If that expression is true
then all
you know at that point the pipeline was playing, but by the time the
next ruby
code is executed it might have stopped playing already. And if it
returns false
then: is it not playing because of an error? Or is it not playing
because it’s
still changing it’s state to playing? Or is it not playing because the
stream
ended (got EOS)?

The right way to write code that depends on state transitions is imho to
watch
for StateChange messages on the bus. element.get_state can be usefull
from
time to time, but one needs to be very carefull with it. That’s also why
i think
it’s good to not have .playing? and friends. It makes it too easy to
write
sublty broken code.

Sjoerd

My geometry teacher was sometimes acute, and sometimes obtuse, but
always,
always, he was right.
[That’s an interesting angle. I wonder if there are any parallels?]

On Sun, Mar 30, 2008 at 12:36:50PM +0200, Sjoerd S. wrote:

serveral outstanding patches of mine are still needed. So not that usefull at
this point. Luckily given the analysis above it’s quite easy to make a trivial
example (attached).

Now actually attached :slight_smile:

Sjoerd

Hi,

In [email protected]
“Re: [ruby-gnome2-devel-en] [patch] Do state calls in a seperate
thread” on Sun, 30 Mar 2008 01:44:41 +0100,
Sjoerd S. [email protected] wrote:

thread in the first place) only sets some flags on the thread, it doesn’t
actually wake up the thread. So the thread only gets run if rb_thread_schedule
is called in the ruby thread, which might take a very long time (maybe
forever).

Could you show the non-trivial example?

wait as these aren't thread-safe. The get_state functions should be
used to get states and/or wait for state changes

Should we remove them? Are they useful?

They are not really usefull… You can get the same information from get_state
and more importantly they don’t take into account that while calling this
function the underlying state might already have changed.

Should we write element.get_state[1] == Gst::STATE_PLAYING
instead of element.playing??

Thanks,

kou

Hi,

In [email protected]
“Re: [ruby-gnome2-devel-en] [patch] Do state calls in a seperate
thread” on Sun, 30 Mar 2008 12:36:50 +0200,
Sjoerd S. [email protected] wrote:

instead of element.playing??

The right way to write code that depends on state transitions is imho to watch
for StateChange messages on the bus. element.get_state can be usefull from
time to time, but one needs to be very carefull with it. That’s also why i think
it’s good to not have .playing? and friends. It makes it too easy to write
sublty broken code.

OK. You can remove them.

Thanks,

kou

This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.

| Privacy Policy | Terms of Service | Remote Ruby Jobs