--- /dev/null
+/*
+ * (C) Copyright 2017 Pantheon Technologies, s.r.o. and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.opendaylight.yangtools.triemap;
+
+import static com.google.common.base.Verify.verify;
+
+import com.google.common.math.IntMath;
+import java.math.RoundingMode;
+
+/**
+ * Various implementation-specific constants shared across classes.
+ *
+ * @author Robert Varga
+ */
+final class Constants {
+ private Constants() {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Size of the hash function, in bits.
+ */
+ static final int HASH_BITS = Integer.SIZE;
+
+ /**
+ * Size of the CNode bitmap, in bits.
+ */
+ static final int BITMAP_BITS = Integer.SIZE;
+
+ /**
+ * Number of hash bits consumed in each CNode level.
+ */
+ static final int LEVEL_BITS = 5;
+ static {
+ verify(LEVEL_BITS == IntMath.log2(BITMAP_BITS, RoundingMode.UNNECESSARY));
+ }
+
+ /**
+ * Maximum depth of a TrieMap.
+ */
+ static final int MAX_DEPTH = 7;
+ static {
+ verify(MAX_DEPTH == IntMath.divide(HASH_BITS, LEVEL_BITS, RoundingMode.CEILING));
+ }
+}
*/
package org.opendaylight.yangtools.triemap;
+import static org.opendaylight.yangtools.triemap.Constants.LEVEL_BITS;
import static org.opendaylight.yangtools.triemap.LookupResult.RESTART;
import static org.opendaylight.yangtools.triemap.PresencePredicate.ABSENT;
import static org.opendaylight.yangtools.triemap.PresencePredicate.PRESENT;
if (cnAtPos instanceof INode) {
final INode<K, V> in = (INode<K, V>) cnAtPos;
if (startgen == in.gen) {
- return in.rec_insert(k, v, hc, lev + 5, this, startgen, ct);
+ return in.rec_insert(k, v, hc, lev + LEVEL_BITS, this, startgen, ct);
}
if (GCAS(cn, cn.renewed(startgen, ct), ct)) {
// Tail recursion: return rec_insert (k, v, hc, lev, parent, startgen, ct);
}
final CNode<K, V> rn = (cn.gen == gen) ? cn : cn.renewed(gen, ct);
- final MainNode<K, V> nn = rn.updatedAt(pos, inode(CNode.dual(sn, k, v, hc, lev + 5, gen)), gen);
+ final MainNode<K, V> nn = rn.updatedAt(pos, inode(CNode.dual(sn, k, v, hc, lev + LEVEL_BITS, gen)), gen);
return GCAS (cn, nn, ct);
}
} else {
return GCAS (cn, ncnode, ct);
}
} else if (m instanceof TNode) {
- clean(parent, ct, lev - 5);
+ clean(parent, ct, lev - LEVEL_BITS);
return false;
} else if (m instanceof LNode) {
final LNode<K, V> ln = (LNode<K, V>) m;
private Optional<V> insertDual(final TrieMap<K, V> ct, final CNode<K, V> cn, final int pos, final SNode<K, V> sn,
final K k, final V v, final int hc, final int lev) {
final CNode<K, V> rn = (cn.gen == gen) ? cn : cn.renewed(gen, ct);
- final MainNode<K, V> nn = rn.updatedAt(pos, inode(CNode.dual(sn, k, v, hc, lev + 5, gen)), gen);
+ final MainNode<K, V> nn = rn.updatedAt(pos, inode(CNode.dual(sn, k, v, hc, lev + LEVEL_BITS, gen)), gen);
return GCAS(cn, nn, ct) ? Optional.empty() : null;
}
if (cnAtPos instanceof INode) {
final INode<K, V> in = (INode<K, V>) cnAtPos;
if (startgen == in.gen) {
- return in.rec_insertif(k, v, hc, cond, lev + 5, this, startgen, ct);
+ return in.rec_insertif(k, v, hc, cond, lev + LEVEL_BITS, this, startgen, ct);
}
if (GCAS(cn, cn.renewed(startgen, ct), ct)) {
return Optional.empty();
}
} else if (m instanceof TNode) {
- clean(parent, ct, lev - 5);
+ clean(parent, ct, lev - LEVEL_BITS);
return null;
} else if (m instanceof LNode) {
// 3) an l-node
if (sub instanceof INode) {
final INode<K, V> in = (INode<K, V>) sub;
if (ct.isReadOnly() || (startgen == in.gen)) {
- return in.rec_lookup(k, hc, lev + 5, this, startgen, ct);
+ return in.rec_lookup(k, hc, lev + LEVEL_BITS, this, startgen, ct);
}
if (GCAS(cn, cn.renewed(startgen, ct), ct)) {
return null;
}
- clean(parent, ct, lev - 5);
+ clean(parent, ct, lev - LEVEL_BITS);
return RESTART;
}
if (sub instanceof INode) {
final INode<K, V> in = (INode<K, V>) sub;
if (startgen == in.gen) {
- res = in.rec_remove(k, cond, hc, lev + 5, this, startgen, ct);
+ res = in.rec_remove(k, cond, hc, lev + LEVEL_BITS, this, startgen, ct);
} else {
if (GCAS(cn, cn.renewed (startgen, ct), ct)) {
res = rec_remove(k, cond, hc, lev, parent, startgen, ct);
return res;
} else if (m instanceof TNode) {
- clean(parent, ct, lev - 5);
+ clean(parent, ct, lev - LEVEL_BITS);
return null;
} else if (m instanceof LNode) {
final LNode<K, V> ln = (LNode<K, V>) m;
}
final CNode<K, V> cn = (CNode<K, V>) pm;
- final int idx = (hc >>> (lev - 5)) & 0x1f;
+ final int idx = (hc >>> (lev - LEVEL_BITS)) & 0x1f;
final int bmp = cn.bitmap;
final int flag = 1 << idx;
if ((bmp & flag) == 0) {
if (sub == this) {
if (nonlive instanceof TNode) {
final TNode<?, ?> tn = (TNode<?, ?>) nonlive;
- final MainNode<K, V> ncn = cn.updatedAt(pos, tn.copyUntombed(), gen).toContracted(lev - 5);
+ final MainNode<K, V> ncn = cn.updatedAt(pos, tn.copyUntombed(), gen).toContracted(lev - LEVEL_BITS);
if (!parent.GCAS(cn, ncn, ct)) {
if (ct.readRoot().gen == startgen) {
// Tail recursion: cleanParent(nonlive, parent, ct, hc, lev, startgen);