Я пишу некоторые функции, которые используют clojure.async для абстракции от чтения/записи до сокетов. Мое намерение состоит в том, что значения могут быть помещены в канал, чтобы они были написаны, и выталкивались из канала для чтения. Таким образом, пользователю не нужно беспокоиться о Reader
s/Writer
s.BufferedReader - Блок в конце потока
Приведенный ниже код считывается из сокета в цикле, пересылая все, что он читает в канал. Канал возвращается, чтобы его можно было прочитать. Моя проблема в том, что когда конец потока достигнут, а не блокируется, он сидит там, пока что-то не читается. Если у меня будет несколько таких процессов, это вызовет заметную проблему с производительностью на моем компьютере.
Самый простой способ, которым я мог это исправить, - это как-то сделать BufferedReader
readLine
блок на EOF вместо возврата nil
. Из того, что я вижу, это невозможно. Это меня не удивляет, поскольку блокировка EOF для большинства потоков будет очень странной. Однако для потоков сокетов EOF, похоже, не имеет определенного значения, поскольку сообщения могут быть получены даже после достижения EOF.
Есть ли способ предотвратить вращение цикла при ожидании ввода после достижения EOF?
(ns chat.so-example
(:require [clojure.core.async :as a :refer [chan go >!]])
(:import [java.net Socket SocketException]
[java.io BufferedReader InputStreamReader InputStream]))
(defn valid-message? [msg]
(and (some? msg)
(not (empty? msg))))
(defn new-input-chan [^Socket sock]
(let [^InputStream in (.getInputStream sock)
buff-reader (BufferedReader. (InputStreamReader. in))
in-chan (chan)]
(go
(try
(while (.isConnected sock) ; This spins when EOF is reached
(let [line (.readLine buff-reader)]
(when (valid-message? line)
(>! in-chan line))))
(catch SocketException se
(#_"Handle exception"))
(finally
(a/close! in-chan))))
in-chan))
Rich Hickey несколько раз заявлял, что это не очень хорошая идея, а не то, что он имел в виду для core.async. Возможно, вы захотите посмотреть его основные разговоры. Полностью понять обоснование этого. Посмотрите на библиотеки Zach Tellmans, такие как коллекторы и алефы, которые реализуют абстракцию, которую вы ищете, и интегрируетесь с core.async. –
@LeonGrapenthin Есть ли у вас ссылки на разговоры? Я бы хотел их посмотреть. :-) – jszakmeister