Mercurial > hg > indyvon
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