View Javadoc

1   /***
2    *  Copyright 2003-2010 Terracotta, Inc.
3    *
4    *  Licensed under the Apache License, Version 2.0 (the "License");
5    *  you may not use this file except in compliance with the License.
6    *  You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   *  Unless required by applicable law or agreed to in writing, software
11   *  distributed under the License is distributed on an "AS IS" BASIS,
12   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   *  See the License for the specific language governing permissions and
14   *  limitations under the License.
15   */
16  
17  package net.sf.ehcache.concurrent;
18  
19  import net.sf.ehcache.CacheException;
20  
21  /***
22   * Various bits of black magic garnered from experts on the   concurrency-interest@cs.oswego.edu mailing list.
23   *
24   * @author Greg Luck
25   * @version $Id: ConcurrencyUtil.html 13146 2011-08-01 17:12:39Z oletizi $
26   */
27  public final class ConcurrencyUtil {
28  
29      private static final int DOUG_LEA_BLACK_MAGIC_OPERAND_1 = 20;
30      private static final int DOUG_LEA_BLACK_MAGIC_OPERAND_2 = 12;
31      private static final int DOUG_LEA_BLACK_MAGIC_OPERAND_3 = 7;
32      private static final int DOUG_LEA_BLACK_MAGIC_OPERAND_4 = 4;
33  
34  
35      /***
36       * Utility class therefore precent construction
37       */
38      private ConcurrencyUtil() {
39          //noop;
40      }
41  
42      /***
43       * Returns a hash code for non-null Object x.
44       * <p/>
45       * This function ensures that hashCodes that differ only by
46       * constant multiples at each bit position have a bounded
47       * number of collisions. (Doug Lea)
48       *
49       * @param object the object serving as a key
50       * @return the hash code
51       */
52      public static int hash(Object object) {
53          int h = object.hashCode();
54          h ^= (h >>> DOUG_LEA_BLACK_MAGIC_OPERAND_1) ^ (h >>> DOUG_LEA_BLACK_MAGIC_OPERAND_2);
55          return h ^ (h >>> DOUG_LEA_BLACK_MAGIC_OPERAND_3) ^ (h >>> DOUG_LEA_BLACK_MAGIC_OPERAND_4);
56      }
57  
58      /***
59       * Selects a lock for a key. The same lock is always used for a given key.
60       *
61       * @param key
62       * @return the selected lock index
63       */
64      public static int selectLock(final Object key, int numberOfLocks) throws CacheException {
65          int number = numberOfLocks & (numberOfLocks - 1);
66          if (number != 0) {
67              throw new CacheException("Lock number must be a power of two: " + numberOfLocks);
68          }
69          if (key == null) {
70              return 0;
71          } else {
72              int hash = hash(key) & (numberOfLocks - 1);
73              return hash;
74          }
75  
76      }
77  
78  }