Hi,

Am 09.11.2008 um 12:23 schrieb Stuart Halloway:
Just to make things even more fun: *None* of the proposed fixes to the
concurrency bug in the original actually preserve the` semantics of
the original. All have moved from "run (usually) once, mark as done"
to "mark as done, try once". This also means that other threads could
see a runonce as being done when it hasn't begun yet.

Hmm.. I have no clue about concurrent programming whatsoever. But
for such cases, maybe an agent would do the trick. Send it the action.
The first time it runs, it calls the function and caches the result.
This could be done maybe with delay/force. Multiple sends would be
automatically be syncronised. But to get the result out of the agent
one would have to pass in a ref, where the results are stored.

(defmacro defrunonce
  [n & body]
  `(def ~n
     (let [agent# (agent (delay [EMAIL PROTECTED]))
           retr#  (fn [state# r-ref#]
                    (let [r# (force state#)]
                      (dosync (ref-set r-ref# r#))))]
       (fn []
         (let [r-ref# (ref nil)]
           (send agent# retr# r-ref#)
           (await agent#)
           (deref r-ref#))))))

user=> (defrunonce foo (println :Run) 5)
#=(var user/foo)
user=> (foo)
:Run
5
user=> (foo)
5

Ok. Maybe this is also only a hack.

Sincerely
Meikel


Attachment: smime.p7s
Description: S/MIME cryptographic signature

Reply via email to