2014-05-15 83 views
0

我有一個TCP套接字連接,我需要在其中處理n請求和conj每個請求,並且它對於用於記錄目的的向量的相應響應。我需要通過兩個異步線程進行傳輸和接收,其中transmit函數負責發送請求,而receive函數負責接收來自服務器的響應。Clojure對共享資源的異步訪問

我的理解是,對於異步傳輸,我需要在Clojure中使用agent來完成此操作。但是,我還需要確保對向量的串行訪問,因爲兩個線程都試圖在任何給定時間對其進行修改。

我試圖讓一些工作正常,但是我的代理在發出幾個請求並處理了一些響應之後最終處於失敗狀態。

以下是顯示我正在嘗試執行的操作的代碼。如果有人能給我一些指導,將不勝感激。

;; 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!定義代理在遇到錯誤時的行爲。