У меня есть соединение сокетов TCP, в котором мне нужно обрабатывать n
запросов и conj
каждый запрос и соответствующий ответ на вектор для ведения журнала. Мне нужно передавать и получать через два асинхронных потока, где функция transmit
отвечает за отправку запросов, а функция receive
отвечает за получение ответов от сервера.Clojure асинхронный доступ к общему ресурсу
Я понимаю, что для асинхронной передачи мне нужно использовать agent
s в Clojure для этого. Тем не менее, мне также необходимо обеспечить последовательный доступ к вектору, так как оба потока пытаются изменить его в любой момент времени.
Я попытался заставить что-то работать, но мой агент попал в состояние неудачи после того, как сделал несколько запросов и обработал несколько ответов.
Ниже приведен код, показывающий, что я пытаюсь сделать. Если бы кто-нибудь мог дать мне какое-то руководство, было бы весьма полезно.
;; the shared resource
(def async-log (agent []))
;; I thought this needed to be synchronized for serial access, so I used
;; dosync, but I am not sure if this is right. In any case, it doesn't
;; seem to make a difference
(defn add-entry
[coll entry]
(dosync (conj coll entry)))
;; transmit function
(defn transmit
[log writer socket request]
(let [request (request->String request socket)
bytes-out (request->bytes request)
length (count bytes-out)]
(.writeShort writer length)
(.write writer bytes-out 0 length)
(add-entry log request)))
;; Receive function
(defn receive
[log reader socket]
(let [length (read-length reader)
bytes-in (byte-array request/max-message-size)]
(.read reader bytes-in 0 length)
(add-entry log (to-string bytes-in))))
;; process each request, n times
(defn process-requests
[request socket iters]
(with-open [reader (DataInputStream. (.getInputStream socket))
writer (DataOutputStream. (.getOutputStream socket))]
(dotimes [x iters]
(send-off async-log transmit writer socket request)
(send-off async-log receive reader socket)
(Thread/sleep 50))))