Mercurial > lasercutter
view 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 source
1 /**2 * Copyright (c) Rich Hickey. All rights reserved.3 * The use and distribution terms for this software are covered by the4 * Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)5 * which can be found in the file epl-v10.html at the root of this distribution.6 * By using this software in any fashion, you are agreeing to be bound by7 * the terms of this license.8 * You must not remove this notice, or any other, from this software.9 **/11 /* rich Jul 31, 2008 */13 package clojure.lang;15 import java.util.concurrent.ConcurrentMap;16 import java.util.*;18 public class TransactionalHashMap<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V>{19 final Ref[] bins;21 IPersistentMap mapAt(int bin){22 return (IPersistentMap) bins[bin].deref();23 }25 final int binFor(Object k){26 //spread hashes, a la Cliff Click27 int h = k.hashCode();28 h ^= (h >>> 20) ^ (h >>> 12);29 h ^= (h >>> 7) ^ (h >>> 4);30 return h % bins.length;31 // return k.hashCode() % bins.length;32 }34 Entry entryAt(Object k){35 return mapAt(binFor(k)).entryAt(k);36 }38 public TransactionalHashMap() throws Exception{39 this(421);40 }42 public TransactionalHashMap(int nBins) throws Exception{43 bins = new Ref[nBins];44 for(int i = 0; i < nBins; i++)45 bins[i] = new Ref(PersistentHashMap.EMPTY);46 }48 public TransactionalHashMap(Map<? extends K, ? extends V> m) throws Exception{49 this(m.size());50 putAll(m);51 }53 public int size(){54 int n = 0;55 for(int i = 0; i < bins.length; i++)56 {57 n += mapAt(i).count();58 }59 return n;60 }62 public boolean isEmpty(){63 return size() == 0;64 }66 public boolean containsKey(Object k){67 return entryAt(k) != null;68 }70 public V get(Object k){71 Entry e = entryAt(k);72 if(e != null)73 return (V) e.getValue();74 return null;75 }77 public V put(K k, V v){78 Ref r = bins[binFor(k)];79 IPersistentMap map = (IPersistentMap) r.deref();80 Object ret = map.valAt(k);81 r.set(map.assoc(k, v));82 return (V) ret;83 }85 public V remove(Object k){86 Ref r = bins[binFor(k)];87 IPersistentMap map = (IPersistentMap) r.deref();88 Object ret = map.valAt(k);89 //checked exceptions are a bad idea, especially in an interface90 try91 {92 r.set(map.without(k));93 }94 catch(Exception e)95 {96 throw new RuntimeException(e);97 }98 return (V) ret;99 }101 public void putAll(Map<? extends K, ? extends V> map){102 for(Iterator i = map.entrySet().iterator(); i.hasNext();)103 {104 Entry<K, V> e = (Entry) i.next();105 put(e.getKey(), e.getValue());106 }107 }109 public void clear(){110 for(int i = 0; i < bins.length; i++)111 {112 Ref r = bins[i];113 IPersistentMap map = (IPersistentMap) r.deref();114 if(map.count() > 0)115 {116 r.set(PersistentHashMap.EMPTY);117 }118 }119 }121 public Set<Entry<K, V>> entrySet(){122 final ArrayList<Map.Entry<K, V>> entries = new ArrayList(bins.length);123 for(int i = 0; i < bins.length; i++)124 {125 IPersistentMap map = mapAt(i);126 if(map.count() > 0)127 entries.addAll((Collection) RT.seq(map));128 }129 return new AbstractSet<Entry<K, V>>(){130 public Iterator iterator(){131 return Collections.unmodifiableList(entries).iterator();132 }134 public int size(){135 return entries.size();136 }137 };138 }140 public V putIfAbsent(K k, V v){141 Ref r = bins[binFor(k)];142 IPersistentMap map = (IPersistentMap) r.deref();143 Entry e = map.entryAt(k);144 if(e == null)145 {146 r.set(map.assoc(k, v));147 return null;148 }149 else150 return (V) e.getValue();151 }153 public boolean remove(Object k, Object v){154 Ref r = bins[binFor(k)];155 IPersistentMap map = (IPersistentMap) r.deref();156 Entry e = map.entryAt(k);157 if(e != null && e.getValue().equals(v))158 {159 //checked exceptions are a bad idea, especially in an interface160 try161 {162 r.set(map.without(k));163 }164 catch(Exception ex)165 {166 throw new RuntimeException(ex);167 }168 return true;169 }170 return false;171 }173 public boolean replace(K k, V oldv, V newv){174 Ref r = bins[binFor(k)];175 IPersistentMap map = (IPersistentMap) r.deref();176 Entry e = map.entryAt(k);177 if(e != null && e.getValue().equals(oldv))178 {179 r.set(map.assoc(k, newv));180 return true;181 }182 return false;183 }185 public V replace(K k, V v){186 Ref r = bins[binFor(k)];187 IPersistentMap map = (IPersistentMap) r.deref();188 Entry e = map.entryAt(k);189 if(e != null)190 {191 r.set(map.assoc(k, v));192 return (V) e.getValue();193 }194 return null;195 }197 }