나는 clojure.async를 사용하여 소켓 읽기/쓰기를 추상화하는 몇 가지 기능을 작성하고 있습니다. 내 의도는 채널에 값을 써서 쓸 수 있고 읽을 채널에서 값을 팝핑 할 수 있다는 것입니다. 이 방법으로 사용자는 Reader
s/Writer
초를 걱정할 필요가 없습니다.BufferedReader - 스트림 끝 부분의 블록
아래 코드는 루프의 소켓에서 읽은 내용을 채널로 전달합니다. 채널을 읽을 수 있도록 반환됩니다. 내 문제는 스트림의 끝에 도달하면 차단하는 대신 뭔가를 읽을 수있을 때까지 회전하는 것입니다. 이러한 프로세스가 몇 개 있으면 내 컴퓨터에서 눈에 띄는 성능 문제가 발생합니다.
이 문제를 해결하는 가장 쉬운 방법은 nil
대신에 BufferedReader
의 readLine
블록이 EOF에있는 것입니다. 내가 볼 수있는 것으로부터 이것은 가능하지 않습니다. 대부분의 스트림에서 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에 대해 생각한 바가 아니라고 말했습니다. 그의 core.async 회담을보고이 배경에 대한 이론적 근거를 완전히 이해하고 싶을 수도 있습니다. 찾고있는 추상화를 구현하고 core.async와 통합 할 수있는 manifold 및 aleph와 같은 Zach Tellmans 라이브러리를 살펴보십시오. –
@LeonGrapenthin에 말씀 하시려는 링크가 있습니까? 나는 그들을보고 싶다. :-) – jszakmeister