is there enough information?

David Bolen db3l.net at gmail.com
Tue Mar 4 18:59:14 EST 2008


Dennis Lee Bieber <wlfraed at ix.netcom.com> writes:

> On Mon, 3 Mar 2008 08:11:43 -0500, Jean-Paul Calderone
> <exarkun at divmod.com> declaimed the following in comp.lang.python:
>
>> I'm not sure, but you seem to be implying that the only way to use Windows'
>> asynchronous I/O APIs is with threads.  Actually, it is possible (and Twisted
>> allows you) to use these as well without writing a threaded application.
>>
> 	I only pointed out that, on Windows, one can not use the common
> /select()/ function with files. And one rarely sees examples of coding a
> Twisted-style (emphasis on style) asynchronous callback system mixing
> files and network sockes using the Windows-specific API.
>
> 	If using threads, the Windows asynchronous I/O isn't needed... let
> the thread block until the I/O completes, then transfer the data (or a
> message that the data is available) back to the main processing
> thread...

You're probably right that it's rare, but when needed, using the
Windows asynchronous/overlapping API can provide a better solution
than blocking threads depending on the needs at hand, and without
involving any callbacks or Twisted-style programming.

An example of mine is high performance serial port handling as part of
a custom FHSS wireless adapter with a serial port interface to the PC.
In this case, minimizing I/O latency was crucial since delays could
mean missing a broadcast timeslot (about 15ms) on the wireless
network.  A serial port isn't a disk file, but certainly a "file" in
the context of Windows handles.

Early implementations used independent threads for reading/writing to
the serial port and blocking during such operations, but that turned
out to have an undesirable amount of latency, and was also difficult
to interrupt when the threads were in a blocked condition.

Instead I created a single thread that had a loop using overlapped I/O
simultaneously in each direction as well as native Windows event
objects for aborting or signaling that there was additional data to be
written (the pending read I/O handled the read case).  The main loop
was just a WaitForMultipleObjects to handle any of the I/O completion
indications, requests for more I/O or aborts.  It was very high
performing (low latency) with low CPU usage - measurably better than a
multi-threaded version.

Communication with the rest of the application was through a
thread-safe bi-directional buffer object, also using native Win32
event objects.  It worked similar to a queue, but by using the native
event objects I didn't have the performance inefficiencies for reads
with timeouts of the Python objects.  The underlying Python primitives
don't have the timeout capability built in, so reads with timeouts get
implemented through checks for data interspersed with increasing
sleeps, which adds unnecessary latency.

Anyway, it worked extremely well, and was a much better fit for my
needs than a multi-threaded version with blocking I/O, without it
having to be Twisted-style.

-- David



More information about the Python-list mailing list