[gst-devel] Multi-threaded queueing locking issues

Erik Walthinsen omega at temple-baptist.com
Tue Mar 20 21:40:49 CET 2001

On Tue, 20 Mar 2001, Matt Howell wrote:

> i agree.  you shouldn't have to use the timed-wait stuff in this case.  also,
> you don't want to use system kill/signal to fix thread scheduling.
> i was thinking something like this: (pseudo-code :)
> gstpad.c::queue_get() - to the while loop, add
>   // somehow, get pendingState
>   if (pendingState == PAUSED) { GST_UNLOCK(lock); return NULL; }
> gstpad.c::queue_chain() - to the while loop, add the same thing
>   if (pendingState == PAUSED) { GST_UNLOCK(lock); return NULL; }
> gstpad.c::change_state() - add
>   {
>     GST_LOCK(queue);
>     signal(emptycond); // wake up waiting queue_get()'s, if any
>     signal(fullcond); // wake up waiting queue_chain()'s, if any
>     GST_UNLOCK(queue);
>   }
> gstscheduler.c::chain_wrapper() - i'm not sure it's necessary, but probably add:
>   if (pendingState == PAUSED) break;  // stop calling pad_pull()'s,
> there may be other places in gstscheduler.c code to do similar.
> thoughts?

The problem is that the above solution only works for queues, and makes
them intimately aware of the threads and vice versa.  The queues aren't
the only things that are going to be blocking.  Anything that attaches to
a file descriptor (file, network, etc.) could also block, and we have to
come up with some way of interrupting them as well.

I'm not sure how one would go about interrupting a blocking read, or the
best way to set it up to time out.  I'd like to find a way (even if it's
element-specific in the form of a special interuption callback) to
interrupt them explicitely, rather than making them spin in a timeout
loop.  That forces them to use select, and other messy stuff.

If it is feasible to construct an interrupt mechanism for every element
that might block, then that may be the solution.  But... note that these
interrupt functions will be run from the top-half's context, not the
thread's context.  That means that they have to be constructed in a
thread-safe manner, which for regular sources is a bit of a stretch.  The
other trick is figuring out which of the elements is currently blocked.
The iterate() code doesn't keep track of that, and can't anyway without a
fair amount of overhead shoving a pointer to the next element somewhere
during every switch.

The advantage of the thread-based signaling approach is that it works
transparently on all elements, because it simply switches them out.  One
other potential issue with that is what happens if the I/O comes back from
a filehandle while the read or write is switched out...?

Hmmm.  This is a hard problem ;-(

      Erik Walthinsen <omega at temple-baptist.com> - System Administrator
       /  \                GStreamer - The only way to stream!
      |    | M E G A        ***** http://gstreamer.net/ *****
      _\  /_

More information about the gstreamer-devel mailing list