changeset 95:df9dedc80485

Atomic add-observer.
author Mikhail Kryshen <mikhail@kryshen.net>
date Thu, 03 Mar 2011 03:20:23 +0300
parents 649d12b6c9ec
children fbedad9bd6de
files src/net/kryshen/indyvon/core.clj
diffstat 1 files changed, 24 insertions(+), 4 deletions(-) [+]
line diff
     1.1 --- a/src/net/kryshen/indyvon/core.clj	Thu Mar 03 03:13:14 2011 +0300
     1.2 +++ b/src/net/kryshen/indyvon/core.clj	Thu Mar 03 03:20:23 2011 +0300
     1.3 @@ -1,5 +1,5 @@
     1.4  ;;
     1.5 -;; Copyright 2010 Mikhail Kryshen <mikhail@kryshen.net>
     1.6 +;; Copyright 2010, 2011 Mikhail Kryshen <mikhail@kryshen.net>
     1.7  ;;
     1.8  ;; This file is part of Indyvon.
     1.9  ;;
    1.10 @@ -23,7 +23,8 @@
    1.11     (java.awt.geom AffineTransform Point2D$Double Rectangle2D$Double Area)
    1.12     (java.awt.event MouseListener MouseMotionListener)
    1.13     (java.awt.font FontRenderContext)
    1.14 -   (com.google.common.collect MapMaker)))
    1.15 +   java.util.concurrent.ConcurrentMap
    1.16 +   com.google.common.collect.MapMaker))
    1.17  
    1.18  ;;
    1.19  ;; Layer context
    1.20 @@ -141,9 +142,28 @@
    1.21  ;; The mechanism used by layers to request repaints
    1.22  ;;
    1.23  
    1.24 -(def ^java.util.Map observers
    1.25 +(def ^ConcurrentMap observers
    1.26       (-> (MapMaker.) (.weakKeys) (.makeMap)))
    1.27  
    1.28 +(defn- cm-replace!
    1.29 +  "Wrap ConcurrentMap replace method to treat nil value as absent
    1.30 +   mapping. Use with maps that does not support nil values."
    1.31 +  [^ConcurrentMap cmap key old new]
    1.32 +  (if (nil? old)
    1.33 +    (nil? (.putIfAbsent cmap key new))
    1.34 +    (.replace cmap key old new)))
    1.35 +
    1.36 +(defn- cm-swap!
    1.37 +  "Atomically swaps the value associated with key in ConcurrentMap
    1.38 +   to be (apply f current-value args). Returns the new value."
    1.39 +  [cmap key f & args]
    1.40 +  (loop []
    1.41 +    (let [old (.get cmap key)
    1.42 +          new (apply f old args)]
    1.43 +      (if (cm-replace! cmap key old new)
    1.44 +        new
    1.45 +        (recur)))))
    1.46 +
    1.47  (defn add-observer
    1.48    "Add observer fn for the target. Watcher identifies the group of
    1.49    observers and could be used to remove the group. Watcher is weakly
    1.50 @@ -152,7 +172,7 @@
    1.51    watcher and target arguments and any additional arguments specified
    1.52    in update call."
    1.53    [watcher target f]
    1.54 -  (.put observers watcher (assoc-cons (.get observers watcher) target f))
    1.55 +  (cm-swap! observers watcher assoc-cons target f)
    1.56    nil)
    1.57  
    1.58  (defn remove-observers