I need to implement a function to read from a port until a certain char is reached, I want it to stop if there is no such char is retrieved from the string. The original intent is to retrieve data from a network connection, but I am testing it with a string for now, why does it fail with a: "*** ERROR IN ##thread-deadlock-action! -- Deadlock detected"? Please find the code below, Regards, Francisco
;; Reads from connection until stop-char appears (define (read-string-until-char connection stop-char) (letrec ((str "") (reader (lambda () (let ((c (read-char connection))) (cond ((or (char=? c stop-char) (eof-object? c)) str) (else (set! str (string-append-char str c)) (reader))))))) (reader) str))
;; Reads from connection until stop-char appears (define (read-string-until-char connection stop-char) (letrec ((str "") (reader (lambda () (let ((c (read-char connection))) (cond ((or (char=? c stop-char) ;it never stops here!! (eof-object? c)) str) (else (set! str (string-append-char str c)) (reader))))))) (reader) str))
;; Appends a char to a string (define (string-append-char str c) (let* ((expanded-str (string-append str " ")) (position (string-length str))) (string-set! expanded-str position c) expanded-str))
(define (with-string-stop str c) (let ((port (open-string str))) (read-string-until-char port c)))
(display (with-string-stop "123456" #\5)) (display (with-string-stop "123456" #\7))
Afficher les réponses par date
On 1-May-08, at 5:50 PM, Francisco wrote:
(define (with-string-stop str c) (let ((port (open-string str))) (read-string-until-char port c)))
"open-string" creates an input-output-port, that is a port you can write to and read from. Whatever you write to it becomes readable (in other words it is a FIFO). So the system cannot tell when the stream is at "end-of-file" because in principle some thread might have a reference to the port and at some point in the future add something to the FIFO. However, the scheduler sees that no other thread is runnable when the read-char is called on an empty FIFO, so it declares that there is a deadlock (no further progress is possible).
So change the open-string by open-input-string (which creates an input- (only)-port) and the end-of-file will be read by read-char as you expect it.
Marc
Marc Feeley wrote:
On 1-May-08, at 5:50 PM, Francisco wrote:
(define (with-string-stop str c) (let ((port (open-string str))) (read-string-until-char port c)))
"open-string" creates an input-output-port, that is a port you can write to and read from. Whatever you write to it becomes readable (in other words it is a FIFO). So the system cannot tell when the stream is at "end-of-file" because in principle some thread might have a reference to the port and at some point in the future add something to the FIFO. However, the scheduler sees that no other thread is runnable when the read-char is called on an empty FIFO, so it declares that there is a deadlock (no further progress is possible).
So change the open-string by open-input-string (which creates an input-(only)-port) and the end-of-file will be read by read-char as you expect it.
Marc
Oh thank you! And what about if want to do it on a network socket, I want to parse the input until a char is found, or until the end of the available input, but according to that input I need to respond using the same socket How do I do that?
Francisco
On 1-May-08, at 7:21 PM, Francisco wrote:
Oh thank you! And what about if want to do it on a network socket, I want to parse the input until a char is found, or until the end of the available input, but according to that input I need to respond using the same socket How do I do that?
You don't need to do anything special. The thread will block when the socket's buffer is empty (waiting for more data to come or the connection to be closed). You won't get a deadlock because the scheduler considers it is possible that the process at the other end of the connection will send more data later.
By the way, if you want to read text until a certain character you can use read-line and specify the character as the second parameter (it defaults to #\newline). Here are some examples:
(read-line (open-input-string "hello world\nhow are you?\n"))
"hello world"
(read-line (open-input-string "hello world\nhow are you?\n") #\space)
"hello"
(define (split str sep)
(read-all (open-input-string str) (lambda (p) (read-line p sep))))
(split "this is a sentence" #\space)
("this" "is" "a" "sentence")
Marc