Lucene.Net  3.0.3
Lucene.Net is a port of the Lucene search engine library, written in C# and targeted at .NET runtime users.
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Properties Pages
SimpleStringInterner.cs
Go to the documentation of this file.
1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements. See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License. You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 using System;
19 
20 namespace Lucene.Net.Util
21 {
22 
23 
24  /// <summary> Simple lockless and memory barrier free String intern cache that is guaranteed
25  /// to return the same String instance as String.intern() does.
26  /// </summary>
28  {
29 
30  internal /*private*/ class Entry
31  {
32  internal /*private*/ System.String str;
33  internal /*private*/ int hash;
34  internal /*private*/ Entry next;
35  internal Entry(System.String str, int hash, Entry next)
36  {
37  this.str = str;
38  this.hash = hash;
39  this.next = next;
40  }
41  }
42 
43  private Entry[] cache;
44  private int maxChainLength;
45 
46  /// <param name="tableSize"> Size of the hash table, should be a power of two.
47  /// </param>
48  /// <param name="maxChainLength"> Maximum length of each bucket, after which the oldest item inserted is dropped.
49  /// </param>
50  public SimpleStringInterner(int tableSize, int maxChainLength)
51  {
52  cache = new Entry[System.Math.Max(1, BitUtil.NextHighestPowerOfTwo(tableSize))];
53  this.maxChainLength = System.Math.Max(2, maxChainLength);
54  }
55 
56  // @Override
57  public override System.String Intern(System.String s)
58  {
59  int h = s.GetHashCode();
60  // In the future, it may be worth augmenting the string hash
61  // if the lower bits need better distribution.
62  int slot = h & (cache.Length - 1);
63 
64  Entry first = this.cache[slot];
65  Entry nextToLast = null;
66 
67  int chainLength = 0;
68 
69  for (Entry e = first; e != null; e = e.next)
70  {
71  if (e.hash == h && (ReferenceEquals(e.str, s) || String.CompareOrdinal(e.str, s) == 0))
72  {
73  // if (e.str == s || (e.hash == h && e.str.compareTo(s)==0)) {
74  return e.str;
75  }
76 
77  chainLength++;
78  if (e.next != null)
79  {
80  nextToLast = e;
81  }
82  }
83 
84  // insertion-order cache: add new entry at head
85  s = String.Intern(s);
86  this.cache[slot] = new Entry(s, h, first);
87  if (chainLength >= maxChainLength)
88  {
89  // prune last entry
90  nextToLast.next = null;
91  }
92  return s;
93  }
94  }
95 }