blob: b65e62f677eca7964b37db646a1452bff4372b09 [file] [log] [blame]
crazyboblee210bf432009-02-05 06:04:18 +00001/*
2 * Written by Doug Lea with assistance from members of JCP JSR-166
3 * Expert Group and released to the public domain, as explained at
4 * http://creativecommons.org/licenses/publicdomain
5 * Other contributors include Andrew Wright, Jeffrey Hayes,
6 * Pat Fisher, Mike Judd.
7 */
8
limpbizkit@gmail.com9a227be2010-07-03 15:51:31 +00009package com.google.inject.internal.util;
crazyboblee210bf432009-02-05 06:04:18 +000010
limpbizkit@gmail.com9a227be2010-07-03 15:51:31 +000011import com.google.inject.internal.util.ForwardingConcurrentMap;
12import com.google.inject.internal.util.CustomConcurrentHashMap;
crazyboblee210bf432009-02-05 06:04:18 +000013import java.io.Serializable;
14import java.util.Map;
15import java.util.concurrent.ConcurrentMap;
16
17/**
18 * A copy of {@link java.util.concurrent.ConcurrentHashMap} used to test {@link
limpbizkit@gmail.com9a227be2010-07-03 15:51:31 +000019 * com.google.inject.internal.util.CustomConcurrentHashMap}. This also serves
crazyboblee210bf432009-02-05 06:04:18 +000020 * as the examples in the CustomConcurrentHashMap Javadocs.
21 */
22public class Jsr166HashMap<K, V> extends ForwardingConcurrentMap<K, V>
23 implements Serializable {
24
25 static class ConcurrentHashMapStrategy<K, V>
26 implements CustomConcurrentHashMap.Strategy<K, V,
27 InternalEntry<K, V>>, Serializable {
28 public InternalEntry<K, V> newEntry(K key, int hash,
29 InternalEntry<K, V> next) {
30 return new InternalEntry<K,V>(key, hash, null, next);
31 }
32 public InternalEntry<K, V> copyEntry(K key,
33 InternalEntry<K, V> original, InternalEntry<K, V> next) {
34 return new InternalEntry<K, V>(key, original.hash, original.value, next);
35 }
36 public void setValue(InternalEntry<K, V> entry, V value) {
37 entry.value = value;
38 }
39 public V getValue(InternalEntry<K, V> entry) { return entry.value; }
40 public boolean equalKeys(K a, Object b) { return a.equals(b); }
41 public boolean equalValues(V a, Object b) { return a.equals(b); }
42 public int hashKey(Object key) { return key.hashCode(); }
43 public K getKey(InternalEntry<K, V> entry) { return entry.key; }
44 public InternalEntry<K, V> getNext(InternalEntry<K, V> entry) {
45 return entry.next;
46 }
47 public int getHash(InternalEntry<K, V> entry) { return entry.hash; }
48 public void setInternals(CustomConcurrentHashMap.Internals<K, V,
49 InternalEntry<K, V>> internals) {} // ignored
50 }
51
52 static class InternalEntry<K, V> {
53 final K key;
54 final int hash;
55 final InternalEntry<K, V> next;
56 volatile V value;
57 InternalEntry(K key, int hash, V value, InternalEntry<K, V> next) {
58 this.key = key;
59 this.hash = hash;
60 this.value = value;
61 this.next = next;
62 }
63 }
64
65 /* ---------------- Public operations -------------- */
66
67 /**
68 * The default initial capacity for this table,
69 * used when not otherwise specified in a constructor.
70 */
71 static final int DEFAULT_INITIAL_CAPACITY = 16;
72
73 /**
74 * The default load factor for this table, used when not
75 * otherwise specified in a constructor.
76 */
77 static final float DEFAULT_LOAD_FACTOR = 0.75f;
78
79 /**
80 * The default concurrency level for this table, used when not
81 * otherwise specified in a constructor.
82 */
83 static final int DEFAULT_CONCURRENCY_LEVEL = 16;
84
85 final ConcurrentMap<K, V> delegate;
86
87 protected ConcurrentMap<K, V> delegate() {
88 return delegate;
89 }
90
91 /**
92 * Creates a new, empty map with the specified initial capacity, load factor
93 * and concurrency level.
94 *
95 * @param initialCapacity the initial capacity. The implementation performs
96 * internal sizing to accommodate this many
97 * elements.
98 * @param loadFactor the load factor threshold, used to control
99 * resizing. Resizing may be performed when the
100 * average number of elements per bin exceeds this
101 * threshold.
102 * @param concurrencyLevel the estimated number of concurrently updating
103 * threads. The implementation performs internal
104 * sizing to try to accommodate this many threads.
105 * @throws IllegalArgumentException if the initial capacity is negative or
106 * the load factor or concurrencyLevel are
107 * nonpositive.
108 */
109 public Jsr166HashMap(int initialCapacity,
110 float loadFactor, int concurrencyLevel) {
111 this.delegate = new CustomConcurrentHashMap.Builder()
112 .initialCapacity(initialCapacity)
113 .loadFactor(loadFactor)
114 .concurrencyLevel(concurrencyLevel)
115 .buildMap(new ConcurrentHashMapStrategy<K, V>());
116 }
117
118 /**
119 * Creates a new, empty map with the specified initial capacity and load
120 * factor and with the default concurrencyLevel (16).
121 *
122 * @param initialCapacity The implementation performs internal sizing to
123 * accommodate this many elements.
124 * @param loadFactor the load factor threshold, used to control
125 * resizing. Resizing may be performed when the
126 * average number of elements per bin exceeds this
127 * threshold.
128 * @throws IllegalArgumentException if the initial capacity of elements is
129 * negative or the load factor is
130 * nonpositive
131 * @since 1.6
132 */
133 public Jsr166HashMap(int initialCapacity, float loadFactor) {
134 this(initialCapacity, loadFactor, DEFAULT_CONCURRENCY_LEVEL);
135 }
136
137 /**
138 * Creates a new, empty map with the specified initial capacity, and with
139 * default load factor (0.75) and concurrencyLevel (16).
140 *
141 * @param initialCapacity the initial capacity. The implementation performs
142 * internal sizing to accommodate this many
143 * elements.
144 * @throws IllegalArgumentException if the initial capacity of elements is
145 * negative.
146 */
147 public Jsr166HashMap(int initialCapacity) {
148 this(initialCapacity, DEFAULT_LOAD_FACTOR, DEFAULT_CONCURRENCY_LEVEL);
149 }
150
151 /**
152 * Creates a new, empty map with a default initial capacity (16), load
153 * factor (0.75) and concurrencyLevel (16).
154 */
155 public Jsr166HashMap() {
156 this(DEFAULT_INITIAL_CAPACITY, DEFAULT_LOAD_FACTOR,
157 DEFAULT_CONCURRENCY_LEVEL);
158 }
159
160 /**
161 * Creates a new map with the same mappings as the given map. The map is
162 * created with a capacity of 1.5 times the number of mappings in the given
163 * map or 16 (whichever is greater), and a default load factor (0.75) and
164 * concurrencyLevel (16).
165 *
166 * @param m the map
167 */
168 public Jsr166HashMap(Map<? extends K, ? extends V> m) {
169 this(Math.max((int) (m.size() / DEFAULT_LOAD_FACTOR) + 1,
170 DEFAULT_INITIAL_CAPACITY),
171 DEFAULT_LOAD_FACTOR, DEFAULT_CONCURRENCY_LEVEL);
172 putAll(m);
173 }
174}