We recognized yesterday that the text delta interface needs to be
turned upside down. Here's the general issue:
When you're writing single-threaded C code to handle data in a
stream-like fashion, there are two approaches you can take:
- `caller pulls': the function that consumes the data calls the
function that produces the data. The producer passes the data to
the consumer via return values, by modifying parameters passed by
reference, etc. The current text delta interface is in this style,
since one calls `svn_next_delta_window' to get the next chunk of
instructions. But `getchar' and `fread' are simpler examples.
- `caller pushes': the function that produces the data calls the
function that consumes the data. The producer passes the data to
the consumer via ordinary parameters. The Expat XML parser
interface is in this style: you call XML_Parse with a chunk of text
to parse, and it invokes your callbacks on each significant thing it
They both work, but they don't mix well: you can't take a `caller
pushes' component and use it to produce data for a `caller pulls'
component, without giving up your streaming behavior.
For example, suppose we're using Expat to parse an XML stream that
containins text delta data. (Contrived, I know.) The *tree* delta
parser invokes Expat, which finds some vcdiff data, and invokes its
character data handler, which wants to call the *text* delta parser.
However, it can't provide an appropriate read_fn, because any further
data that function may need is still in Expat's internal buffer. And
you can't call Expat recursively, because Expat may find the end of
the vcdiff data, and want to invoke its StartElementHandler and
EndElementHandler, even though the tree delta parser is still waiting
for its character data handler to return. ("Don't call us, we'll call
It could be made to work by having Expat run in a separate thread,
interacting with the text delta code in a coroutine-ish kind of way,
but making the Subversion delta library require thread support is a
It's not a huge problem: we just invert the text delta interface to be
`caller pushes' instead of `caller pulls'. Event-driven and
`select'-driven environments are more friendly to pushing anyway, so
this is probably a good thing.
Perhaps this is more explanation than needed, but I didn't want you to
feel like we were just jerking you around, and changing interfaces by
whim. If you see some clean way to make things work together, let me
know, but I think it's simplest just to change the text delta
interface. Probably you'll be able to share a lot of code --- I hope
so, at least.
Received on Sat Oct 21 14:36:06 2006