0

I don't understand why my code doesn't work. I have a vector, this vector contains input-ports on certain locations and 0 on other locations. When there is an input port, I want to check if there is data available. If there is data available, read it and enqueue it. If there isn't, move on.

Here's my code:

;The name of the vector is 'in'.
(define (read-ports)
  (let loop
    ((idx 0))
    (if (not (= idx (vector-length in)))
        (let ((port (vector-ref in idx)))
          (if (not (eq? port 0))
              (if (char-ready? port)
                  (let ((data (read port)))
                    (sendm buffer 'enqueue! data)) ;my own queue
                  (loop (+ idx 1)))
              (loop (+ idx 1))))
        'done)))

My problem is, char-ready returns true, but the read operation still blocks! I'm sure the data is being send, but then why does it block? The data I am trying to send are vectors, but these contain values between 0 en 255. So actually they are vectors of bytes.

Thanks in advance

JNevens
  • 11,202
  • 9
  • 46
  • 72
  • 3
    `char-ready?` is true if you can use `read-byte`, not `read`. – uselpa May 21 '14 at 10:45
  • Is there something I can use to check if `read` is going to block? – JNevens May 21 '14 at 10:48
  • Are you sure you need `read`? I would look into the `read-bytes-*` and `peek-*` procedures. – uselpa May 21 '14 at 10:54
  • Also, you can greatly simplify your code using `for` loops or `for-each`. – uselpa May 21 '14 at 10:56
  • I'm sending `vectors`. But these contain values between 0 en 255, so `bytes` essentially. Can I read these vectors-of-bytes with `read-bytes` or do I have to cast them to something else? – JNevens May 21 '14 at 10:58

1 Answers1

1

To answer your question as-asked:

read blocks until it can read a complete s-expression. As a result, if you are trying to read the vector #(1 2 3 4), the bytes for the #(1 2 part may be available to read now -- but not necessarily the bytes for the remaining 3 4).


To make a general suggestion:

Although I don't know the context of what you want to accomplish, it sounds like you have N input-ports, and your read-ports function will try to read a vector from each port, putting the result in some central buffer, then return 'done. (I'm not sure if you will call read-ports once, or repeatedly.)

A better design probably would be to make a thread to read each port, and have each thread put its result in a central buffer by using an async-channel to guard/coordinate access to that buffer. So you'd have N threads, each reading one of the N ports.

This way, you don't need to worry about blocking -- each thread calls read, and it is done when it is done. (OTOH this design would mean the vectors could be read out of order; if that matters, you could handle it in a few ways.)

Again, I don't know your exact goal, but basically I'm suggesting to work "with" Racket by using its lightweight green threads and channels.

Greg Hendershott
  • 16,100
  • 6
  • 36
  • 53