An improvement to Queue
Michael Abbott
michael at rcp.co.uk
Fri Feb 1 04:07:44 EST 2002
"Tim Peters" <tim.one at home.com> wrote in
news:mailman.1012515655.8263.python-list at python.org:
> [Michael Abbott]
>> It's the transition from empty to non-empty that's important: I know
>> that the consumer will consume until there's nothing left (that's part
>> of the contract), and the producer should be able to promise not to
>> pester the consumer until it has finished its previous round of work.
>
> It *sounds* like you're using Queue to manipulate items at too low a
> level of granularity. If you created a class to encapsulate the notion
> of "one round of work", then the consumer could pull off "one complete
> round of work" per Queue.get(), and you wouldn't need other synch
> gimmicks (or other complications) to communicate where "one round of
> work's" boundaries lie.
The problem is that when the consumer gets around to performing its round
of work, rather than just performing the "jobs" in sequence and in
isolation, in fact the the consumer is in a position to merge jobs together
into a single action.
Think of a cursor addressable terminal the wrong end of a serial line (this
is close to my application): sending characters down the serial line is the
main limiting resource, and the "consumer" in this case is in the business
of formatting up an incremental update and sending it on.
However, changes to the display are coming in all the time, too fast to
display, on a separate thread. I therefore want to accumulate these
changes and when there is room on the serial line send the entire batch.
The consumer should therefore be spending most of its time waiting for the
serial line to become free, and then formatting up a batch of updates.
Arguably this accumulation should be done in the generating thread, but I
don't really wish to do it that way in this particular case. In
particular, the model I propose makes synchronisation almost trivial, which
is I think quite an important consideration!
>> However, the question is: what am I going to do with a command that's
>> ready to be executed? The problem is, the code that's going to obey
>> the command might not be ready for it,
>
> If the consumer pulls off a "one round of work" object, then presumably
> it won't *try* another Queue.get() until it is ready for another round
> of work. Queue exists to mediate potentially mismatching flow rates,
> not to supply a brittle way to perform aggregation <wink>.
Brittle? Surely not. I guess that's my point: if I have mis-matched flows
between two threads, and as you point out, I want to perform aggregation of
the data, I would like the option of performing this aggregation either
side of the flow. Having the consumer aggregate is simpler (though, of
course, has its own problems).
One thing I have learnt in doing a fair amount of (soft) real time data
redistribution (in C[++]) is to keep event triggers and thread context
switches under control: they cost, particularly if you are dealing with
many thousands of events.
(Unfortunately, Python seems less suited to this approach, given the 2
orders of magnitude cost we pay up front for using the language, but that's
another story.)
More information about the Python-list
mailing list