[plt-scheme] Need low-level help: blocking on reading from serial port in Windows

From: Carl Eastlund (carl.eastlund at gmail.com)
Date: Thu Oct 22 18:31:27 EDT 2009

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


Posted on the users mailing list.