On Sat, Feb 14, 2009 at 5:44 PM, James Reeves <weavejes...@googlemail.com>wrote:
> > On Feb 14, 5:30 pm, Dan <redalas...@gmail.com> wrote: > > What about making the file an agent and sending write actions to it? > > I don't see how that would solve the problem, unless you're suggesting > that I have a single agent to handle all reads and writes? > > - James > Temp files is probably the simplest way to go for "immutable" files. I tried a temporary agent per file, and it got a little long. To support multiple writes with interleaved reads and figuring out when to dissoc the agent would probably make it even longer. (ns safe-write (:import (java.io File)) (:use [clojure.contrib.duck-streams :as ds])) (def writers (ref {})) (defn noop "Sends a noop action to an agent and awaits it." [agt] (send-off agt #(identity %)) (await agt)) (defn await-writer "Waits for f's writer agent to finish if there is one and returns it. Else returns nil." [f] (when-let [agt (@writers f)] (while (not (= @agt :done)) (noop agt)) agt)) (defn exists? [f] (.exists (File. f))) (defn waiting-read "Reads f, waiting for it to be written if another thread is writing it." [f] (await-writer f) (when (exists? f) (slurp f))) (defn create-writer "Creates an agent to write f and returns it. Returns nil if such an agent already exists." [f] (dosync (when-not (@writers f) (let [agt (agent :working)] (alter writers assoc f agt) agt)))) (defn safe-write-once "Writes contents to f, but only if it doesn't exist and no other thread is writing it." [f contents] (when-not (exists? f) (when-let [writer (create-writer f)] (send-off writer (fn [_] ;;(Thread/sleep 2000) (spit f contents) :done)) (await writer) (dosync (alter writers dissoc f))))) (defn do-test [] (let [f "/tmp/test4.txt"] (.delete (File. f)) (.start (Thread. #(safe-write-once f "crino"))) (Thread/sleep 0) (waiting-read f))) --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~----------~----~----~----~------~----~------~--~---