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