On Tue, Jun 30, 2009 at 10:10, Daniel B Lucraft<[email protected]> wrote:
>
> I didn't think it was possible for the render agent to be interrupted
> like that. Isn't the point of the MVCC system that the render agent
> will see a consistent view of the world as it was when the render
> started? And that the ants can continue modifying the world during the
> render's processing but the render agent will not see any of it until
> it has completed it's transaction? It only reads the refs so it
> shouldn't ever retry.
>
> Sorry to jump in despite being inexperienced at this, but it makes me
> think I don't understand something correctly.
>
To demonstrate my point, I made the following changes to my copy of ants.clj:
----------------------- [[ patch on ants.clj ]] ----------------------------
Changes in HEAD
Modified ants.clj
diff --git a/ants.clj b/ants.clj
index 5e2e012..43e3ba0 100644
--- a/ants.clj
+++ b/ants.clj
@@ -262,11 +262,14 @@
(render-ant (:ant p) g x y)))
(defn render [g]
- (let [v (dosync (apply vector (for [x (range dim) y (range dim)]
- @(place [x y]))))
+ (println "entering render")
+ (let [v (dosync (println "snapshotting world")
+ (apply vector (for [x (range dim) y (range dim)]
+ @(place [x y]))))
img (new BufferedImage (* scale dim) (* scale dim)
(. BufferedImage TYPE_INT_ARGB))
bg (. img (getGraphics))]
+ (println "rendering world")
(doto bg
(.setColor (. Color white))
(.fillRect 0 0 (. img (getWidth)) (. img (getHeight))))
@@ -278,7 +281,8 @@
(.drawRect (* scale home-off) (* scale home-off)
(* scale nants-sqrt) (* scale nants-sqrt)))
(. g (drawImage img 0 0 nil))
- (. bg (dispose))))
+ (. bg (dispose))
+ (println "exiting render")))
(def panel (doto (proxy [JPanel] []
(paint [g] (render g)))
--------------------- [[ end patch on ants.clj ]] --------------------------
After evaluating:
(def ants (setup))
(send-off animator animation)
I saw output like this:
entering render
snapshotting world
rendering world
exiting render
entering render
snapshotting world
rendering world
exiting render
...
After evaluating this, which starts up all the ants and the evaporator
thread:
(dorun (map #(send-off % behave) ants))
(send-off evaporator evaporation)
I'm now seeing this:
entering render
snapshotting world
snapshotting world
snapshotting world
snapshotting world
snapshotting world
snapshotting world
snapshotting world
snapshotting world
snapshotting world
snapshotting world
...
Clearly "snapshotting world" is getting retried. This makes a certain
degree of sense from skimming LockingTransaction, which ultimately
implements dosync.
I'm *guessing* that it records a readPoint (a kind of transactional
'timestamp') when it starts working and makes sure that this readPoint
is never less than any consulted reference's (last modification)
point. Such a constellation indicates that the reference has been
changed since the start of the transaction. To recover from this,
clojure does a retry. This it will do 10'000 times before giving up. I
don't believe I ever actually waited that long. ;-)
// ben
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to [email protected]
Note that posts from new members are moderated - please be patient with your
first post.
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
-~----------~----~----~----~------~----~------~--~---