guile-user
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Concurrently write (out) and read (in) from ports


From: Zelphir Kaltstahl
Subject: Concurrently write (out) and read (in) from ports
Date: Tue, 11 Apr 2023 21:13:19 +0000

Hi Guile users!

I am currently trying to concurrently write to an output port and read from the corresponding input port, but something I am doing wrong and it does not work as I expected it to.

Here is what I have tried so far:

~~~~
(import
 ;; ports
 (ice-9 popen)
 (ice-9 textual-ports)
 (ice-9 binary-ports)

 (ice-9 exceptions)
 (ice-9 match)
 (ice-9 threads)
 (ice-9 futures)
 ;; let-values form
 (srfi srfi-11))


;; Define a pair of corresponding in and out ports.
(define-values (in out)
  (match-let ([(in . out) (pipe)])
    ;; make out line buffered
    ;; (setvbuf out 'line)
    (values in out)))


;; Just a helper function.
(define seconds
  (λ (s)
    (* s (expt 10 6))))


(define line-reader
  (λ ()
    "Read from an IN-PORT and write to OUT-PORT."
    (let ([in-port (current-input-port)]
          [out-port (current-output-port)])
      (let loop ([line (get-line in-port)])
        (simple-format #t "reader: reading from in-port\n")
        (unless (eof-object? line)
          (put-string out-port line)
          (loop (get-line in-port)))))))


;; Start writing endlessly.
(define writer-future
  (future
   (with-output-to-port out
     (λ () (endless-writer)))))


(with-output-to-port (current-output-port)
  (λ ()
    (with-input-from-port in
      (line-reader))))
~~~~

However, this does not work:

~~~~
guile -L . example.scm
~~~~

Does not display anything.

I also tried with explicitly passed ports:

~~~~
(import
 ;; ports
 (ice-9 popen)
 (ice-9 textual-ports)
 (ice-9 binary-ports)
 (ice-9 exceptions)
 ;; receive form
 ;; (ice-9 receive)
 ;; pattern matching
 (ice-9 match)
 ;; concurrency
 (ice-9 threads)
 (ice-9 futures)
 ;; let-values form
 (srfi srfi-11))


(define-values (in out)
  (match-let ([(in . out) (pipe)])
    ;; make out line buffered
    ;; (setvbuf out 'none)
    (values in out)))


(define seconds
  (λ (s)
    (* s (expt 10 6))))


(define endless-writer
  (λ (out)
    (let loop ()
      (simple-format #t "writer: writing message to output port\n")
      (put-string out "Hello!\n")
      ;; forcing the output should be unnecessary
      ;; (force-output out)
      (usleep (seconds 1))
      (loop))
    'never))


(define line-reader
  (lambda* (in-port out-port)
    "Read from an IN-PORT and write to OUT-PORT."
    (let loop ([line (get-line in-port)])
      (simple-format #t "reader: reading from in-port\n")
      (unless (eof-object? line)
        (put-string out-port line)
        (loop (get-line in-port))))))


;; Start writing endlessly.
(define writer-future (future (endless-writer out)))


;; Read from in-port, which should be the corresponding one to the
;; out-port, to which the endless-writer writes its output. Output to
;; the current output port, so that the output is visible. Read some
;; number of bytes at once. Limits the amount of memory needed for the
;; string.

(reader in (current-output-port) #:bytes-count 16)

;; That does not output anything.

(line-reader in (current-output-port))

;; That does not output anything.
~~~~

But:

~~~~
(call-with-input-string "Test!\n"
  (lambda (in)
    (line-reader in (current-output-port))))
~~~~

Does output things.

So I am thinking my endless writer must be wrong. But I cannot figure out what is wrong. Or maybe I am misunderstanding how the in and out port of (pipe) correspond.

How can I make this work?

Also side question: Is this usage of futures "OK", or should I be using threads? Thought futures are more lightweight than threads in this case.

Regards,
Zelphir

--
repositories:https://notabug.org/ZelphirKaltstahl


reply via email to

[Prev in Thread] Current Thread [Next in Thread]