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 +}