I guess conceptually the problem here is that a GStreamer element might request and fill exactly as many buffers as we have in our quartz pool, but not actually chain any of them to us, and demand to read more before chaining (but not to allocate more samples)? That's quite pathological, does this actually happen?
Or is there a simpler deadlock I'm missing? I can't come up with anything that's not along the lines of "GStreamer demands more buffers than the quartz pool has", which would deadlock *anyway* regardless of whether it's synchronized with read requests.
Not necessarily, it would block the demanding thread, and synchronize it with the client thread only. This is a much smaller constraint than synchronizing all the involved threads toghether. That constraint alone usually stands because indeed, streams threads are consuming the samples they are producing, but I don't see any reason why different streams synchronized toghether would necessarily end up consuming the samples in an order that would always satisfy the same constraints.
I could spend time trying to find out an example, but to be honest I don't understand why I need to and I don't think it's even worth it, we can simply avoid the problem altogether by avoiding unnecessary synchronization.
Maybe I can point a gun at my feet and not get shot but my usual strategy is to not even try, especially when debugging such deadlocks is notoriously difficult as the number of threads involved is huge.
All else aside, I'd really rather have many simple and modular entry points than one complex one. In general, writing a lot of boilerplate is preferable to me than writing code that's hard to follow.
I think multiplying the number of entry points is making things more complicated rather than less, and more error prone. If we need boilerplate for that I think we're doing it wrong.
I'm less worried about the simplicity of the interface (although I do think there are ways we could make this design friendlier) and more worried about the back-end code. I think it's very hard to follow already, and this is going to make it worse.
Ah thanks for pointing that out, because the design also reduces the complexity there: it merges the read_cond, read_done_cond and all the streams event_cond, event_empty_cond variables together using a single requests list, and request_cond, request_done_cond variables.