# HG changeset patch
# User Mikhail Kryshen <mikhail@kryshen.net>
# Date 1416784153 -10800
# Node ID 4aa8979938eeafd69f42dd6a5bd88d319fe12572
# Parent  acda6344bcb7edc638a504593dd0d0a238088259
Faster dynamic bindings.

diff -r acda6344bcb7 -r 4aa8979938ee src/indyvon/core.clj
--- a/src/indyvon/core.clj	Sat Nov 22 03:49:31 2014 +0300
+++ b/src/indyvon/core.clj	Mon Nov 24 02:09:13 2014 +0300
@@ -338,6 +338,24 @@
        (swap! (:next-state scene) assoc handle state)
        (update scene))))
 
+(defmacro binding-fast
+  "Faster alternative to core/binding. Works only with vars that are
+  already thread-bound. Uses set! instead of push-thread-bindings and
+  pop-thread-bindings."
+  [bindings & body]
+  {:pre [(vector? bindings)
+         (even? (count bindings))]}
+  (let [bindings (partition 2 bindings)
+        var-syms (map first bindings)
+        var-vals (map second bindings)
+        syms (map (comp gensym name) var-syms)]
+    `(let [~@(mapcat vector syms var-syms)]
+       (try
+         ~@(map #(list `set! %1 %2) var-syms var-vals)
+         ~@body
+         (finally
+           ~@(map #(list `set! %1 %2) var-syms syms))))))
+
 ;;
 ;; Rendering
 ;;
@@ -446,10 +464,10 @@
   (let [graphics (create-graphics)]
     (try
       (.translate graphics (double x) (double y))
-      (binding [*width* w
-                *height* h
-                *input-clip* (Rectangle2D$Double. 0.0 0.0 w h)
-                *graphics* graphics]
+      (binding-fast [*width* w
+                     *height* h
+                     *input-clip* (Rectangle2D$Double. 0.0 0.0 w h)
+                     *graphics* graphics]
         (apply f args))
       (finally
        (.dispose graphics)))))
@@ -464,11 +482,11 @@
         (try
           (.clip graphics bounds)
           (.translate graphics x y)
-          (binding [*width* w
-                    *height* h
-                    *clip* clip
-                    *input-clip* nil
-                    *graphics* graphics]
+          (binding-fast [*width* w
+                         *height* h
+                         *clip* clip
+                         *input-clip* nil
+                         *graphics* graphics]
             (apply f args))
           (finally
            (.dispose graphics)))))))
@@ -565,7 +583,7 @@
   ([view]
      (let [graphics (create-graphics)]
        (try
-         (binding [*graphics* graphics]
+         (binding-fast [*graphics* graphics]
            (render! view))
          (finally
           (.dispose graphics)))))
@@ -602,8 +620,8 @@
 
 (defn with-handlers*
   [handle handlers f & args]
-  (binding [*event-dispatcher* (create-dispatcher
-                                *event-dispatcher* handle handlers)]
+  (binding-fast [*event-dispatcher* (create-dispatcher
+                                     *event-dispatcher* handle handlers)]
     (apply f args)))
 
 (defmacro with-handlers