[plt-scheme] Need low-level help: blocking on reading from serial port in Windows
On Thu, Oct 22, 2009 at 6:10 PM, Nadeem Abdul Hamid <nadeem at acm.org> wrote:
> Hello all,
>
> I'm working on a Scheme interface to some robots and am having issues with
> reading from a serial port (really a wireless Bluetooth connection) on
> Windows. Basically, I need help writing a function that efficiently reads
> data from the port (without running into deadlock apparently). Here's the
> function in question; it's supposed to read a specified number of bytes from
> the input port in a "bot" structure and return them in a list:
>
> ;; raw-read : number bot -> (listof byte)
> (define (raw-read n a-bot)
> ;(printf " raw-read")
> (local (;; read-aux : (listof byte) number port -> (listof byte)
> (define (read-aux acc n in)
> ;(sleep (/ LATENCY 1000))
> ;(printf ".~a" acc)
> (cond
> [(= n 0) acc]
> [else
> (cond
> [(byte-ready? in) (read-aux (cons (read-byte in) acc)
> (- n 1) in)]
> [else (read-aux acc n in)])]))
> (define r (reverse (read-aux empty n (bot-in-port a-bot)))))
> ;(printf " done: ~a\n" r)
> r
> ))
>
> First, everything works fine beautifully on Mac OS X. Then I went to try
> this on Windows XP (using PLT Scheme 4.2.2) and it would hang in this
> function. I've finally figured out that if I uncomment the "sleep"
> statement, then it does *not* hang. However, that makes performance very
> sluggish (even though LATENCY is defined as .01). So I'm wondering if
> without the sleep there is some sort of deadlock happening with the
> byte-ready? function? I suppose I could keep a counter and only "sleep"
> every 100 or 1000 failures of the byte-ready? condition, but does anyone
> have suggestions for a better way to do this? To tell the truth, I don't
> remember why I used byte-ready? to begin with -- in the morning I'll try
> without it and see what happens by just letting "read-byte" block until
> there's data.
>
> The port in the "bot" structure was opened using:
> (open-input-output-file portname #:mode 'binary #:exists 'update)
> where on windows portname is something like "\\\\.\\COM10".
>
>
> Thanks in advance for suggestions, comments. I'm still a Scheme newbie so
> welcome any criticisms :-)
>
> --- nadeem
Nadeem,
You may want to look at the read-bytes-avail* function:
http://docs.plt-scheme.org/reference/Byte_and_String_Input.html#(def._((quote._~23~25kernel)._read-bytes-avail!*))
It reads a byte string from a port and returns it immediately, never
blocking. It looks like it does the work for you.
--Carl