2014-05-15 4 views
0

У меня есть соединение сокетов 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)))) 

ответ

1

Вы правы, что ваш dosync там не требуется.

Если проблема заключается в том, что ваш агент входит в состояние ошибки, то вы должны использовать следующие функции:

agent-error исследовать ошибки на агента.

restart-agent, чтобы сбросить состояние ошибки агента, чтобы оно могло работать снова.

set-error-handler!, чтобы определить поведение агента при его возникновении.

Смежные вопросы