package org.infinispan.util; /** * An hash function for stripping. * <p> * It calculates the number of segments based on the concurrency level desired and hashes the object to the * corresponding segments. * * @author Pedro Ruivo * @since 8.0 */ public class StripedHashFunction<T> { private final int lockSegmentMask; private final int lockSegmentShift; private final int numSegments; public StripedHashFunction(int concurrencyLevel) { int tempLockSegShift = 0; int tmpNumSegments = 1; while (tmpNumSegments < concurrencyLevel) { ++tempLockSegShift; tmpNumSegments <<= 1; } lockSegmentShift = 32 - tempLockSegShift; lockSegmentMask = tmpNumSegments - 1; numSegments = tmpNumSegments; } /** * @param hashCode the object's hash code serving as a key. * @return the hash code of the key */ private static int hash(int hashCode) { int h = hashCode; h += ~(h << 9); h ^= (h >>> 14); h += (h << 4); h ^= (h >>> 10); return h; } /** * @return the number of segments. */ public final int getNumSegments() { return numSegments; } /** * It calculates the segment in which the object belongs. * * @param object the object to hash. * @return the segment index, between 0 and {@link #getNumSegments()}-1. */ public final int hashToSegment(T object) { return (hash(object.hashCode()) >>> lockSegmentShift) & lockSegmentMask; } }