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