Mercurial > lasercutter
diff src/clojure/lang/TransactionalHashMap.java @ 10:ef7dbbd6452c
added clojure source goodness
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Sat, 21 Aug 2010 06:25:44 -0400 |
parents | |
children |
line wrap: on
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/clojure/lang/TransactionalHashMap.java Sat Aug 21 06:25:44 2010 -0400 1.3 @@ -0,0 +1,197 @@ 1.4 +/** 1.5 + * Copyright (c) Rich Hickey. All rights reserved. 1.6 + * The use and distribution terms for this software are covered by the 1.7 + * Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 1.8 + * which can be found in the file epl-v10.html at the root of this distribution. 1.9 + * By using this software in any fashion, you are agreeing to be bound by 1.10 + * the terms of this license. 1.11 + * You must not remove this notice, or any other, from this software. 1.12 + **/ 1.13 + 1.14 +/* rich Jul 31, 2008 */ 1.15 + 1.16 +package clojure.lang; 1.17 + 1.18 +import java.util.concurrent.ConcurrentMap; 1.19 +import java.util.*; 1.20 + 1.21 +public class TransactionalHashMap<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V>{ 1.22 +final Ref[] bins; 1.23 + 1.24 +IPersistentMap mapAt(int bin){ 1.25 + return (IPersistentMap) bins[bin].deref(); 1.26 +} 1.27 + 1.28 +final int binFor(Object k){ 1.29 + //spread hashes, a la Cliff Click 1.30 + int h = k.hashCode(); 1.31 + h ^= (h >>> 20) ^ (h >>> 12); 1.32 + h ^= (h >>> 7) ^ (h >>> 4); 1.33 + return h % bins.length; 1.34 +// return k.hashCode() % bins.length; 1.35 +} 1.36 + 1.37 +Entry entryAt(Object k){ 1.38 + return mapAt(binFor(k)).entryAt(k); 1.39 +} 1.40 + 1.41 +public TransactionalHashMap() throws Exception{ 1.42 + this(421); 1.43 +} 1.44 + 1.45 +public TransactionalHashMap(int nBins) throws Exception{ 1.46 + bins = new Ref[nBins]; 1.47 + for(int i = 0; i < nBins; i++) 1.48 + bins[i] = new Ref(PersistentHashMap.EMPTY); 1.49 +} 1.50 + 1.51 +public TransactionalHashMap(Map<? extends K, ? extends V> m) throws Exception{ 1.52 + this(m.size()); 1.53 + putAll(m); 1.54 +} 1.55 + 1.56 +public int size(){ 1.57 + int n = 0; 1.58 + for(int i = 0; i < bins.length; i++) 1.59 + { 1.60 + n += mapAt(i).count(); 1.61 + } 1.62 + return n; 1.63 +} 1.64 + 1.65 +public boolean isEmpty(){ 1.66 + return size() == 0; 1.67 +} 1.68 + 1.69 +public boolean containsKey(Object k){ 1.70 + return entryAt(k) != null; 1.71 +} 1.72 + 1.73 +public V get(Object k){ 1.74 + Entry e = entryAt(k); 1.75 + if(e != null) 1.76 + return (V) e.getValue(); 1.77 + return null; 1.78 +} 1.79 + 1.80 +public V put(K k, V v){ 1.81 + Ref r = bins[binFor(k)]; 1.82 + IPersistentMap map = (IPersistentMap) r.deref(); 1.83 + Object ret = map.valAt(k); 1.84 + r.set(map.assoc(k, v)); 1.85 + return (V) ret; 1.86 +} 1.87 + 1.88 +public V remove(Object k){ 1.89 + Ref r = bins[binFor(k)]; 1.90 + IPersistentMap map = (IPersistentMap) r.deref(); 1.91 + Object ret = map.valAt(k); 1.92 + //checked exceptions are a bad idea, especially in an interface 1.93 + try 1.94 + { 1.95 + r.set(map.without(k)); 1.96 + } 1.97 + catch(Exception e) 1.98 + { 1.99 + throw new RuntimeException(e); 1.100 + } 1.101 + return (V) ret; 1.102 +} 1.103 + 1.104 +public void putAll(Map<? extends K, ? extends V> map){ 1.105 + for(Iterator i = map.entrySet().iterator(); i.hasNext();) 1.106 + { 1.107 + Entry<K, V> e = (Entry) i.next(); 1.108 + put(e.getKey(), e.getValue()); 1.109 + } 1.110 +} 1.111 + 1.112 +public void clear(){ 1.113 + for(int i = 0; i < bins.length; i++) 1.114 + { 1.115 + Ref r = bins[i]; 1.116 + IPersistentMap map = (IPersistentMap) r.deref(); 1.117 + if(map.count() > 0) 1.118 + { 1.119 + r.set(PersistentHashMap.EMPTY); 1.120 + } 1.121 + } 1.122 +} 1.123 + 1.124 +public Set<Entry<K, V>> entrySet(){ 1.125 + final ArrayList<Map.Entry<K, V>> entries = new ArrayList(bins.length); 1.126 + for(int i = 0; i < bins.length; i++) 1.127 + { 1.128 + IPersistentMap map = mapAt(i); 1.129 + if(map.count() > 0) 1.130 + entries.addAll((Collection) RT.seq(map)); 1.131 + } 1.132 + return new AbstractSet<Entry<K, V>>(){ 1.133 + public Iterator iterator(){ 1.134 + return Collections.unmodifiableList(entries).iterator(); 1.135 + } 1.136 + 1.137 + public int size(){ 1.138 + return entries.size(); 1.139 + } 1.140 + }; 1.141 +} 1.142 + 1.143 +public V putIfAbsent(K k, V v){ 1.144 + Ref r = bins[binFor(k)]; 1.145 + IPersistentMap map = (IPersistentMap) r.deref(); 1.146 + Entry e = map.entryAt(k); 1.147 + if(e == null) 1.148 + { 1.149 + r.set(map.assoc(k, v)); 1.150 + return null; 1.151 + } 1.152 + else 1.153 + return (V) e.getValue(); 1.154 +} 1.155 + 1.156 +public boolean remove(Object k, Object v){ 1.157 + Ref r = bins[binFor(k)]; 1.158 + IPersistentMap map = (IPersistentMap) r.deref(); 1.159 + Entry e = map.entryAt(k); 1.160 + if(e != null && e.getValue().equals(v)) 1.161 + { 1.162 + //checked exceptions are a bad idea, especially in an interface 1.163 + try 1.164 + { 1.165 + r.set(map.without(k)); 1.166 + } 1.167 + catch(Exception ex) 1.168 + { 1.169 + throw new RuntimeException(ex); 1.170 + } 1.171 + return true; 1.172 + } 1.173 + return false; 1.174 +} 1.175 + 1.176 +public boolean replace(K k, V oldv, V newv){ 1.177 + Ref r = bins[binFor(k)]; 1.178 + IPersistentMap map = (IPersistentMap) r.deref(); 1.179 + Entry e = map.entryAt(k); 1.180 + if(e != null && e.getValue().equals(oldv)) 1.181 + { 1.182 + r.set(map.assoc(k, newv)); 1.183 + return true; 1.184 + } 1.185 + return false; 1.186 +} 1.187 + 1.188 +public V replace(K k, V v){ 1.189 + Ref r = bins[binFor(k)]; 1.190 + IPersistentMap map = (IPersistentMap) r.deref(); 1.191 + Entry e = map.entryAt(k); 1.192 + if(e != null) 1.193 + { 1.194 + r.set(map.assoc(k, v)); 1.195 + return (V) e.getValue(); 1.196 + } 1.197 + return null; 1.198 +} 1.199 + 1.200 +}