Index: src/java/org/apache/lucene/util/StringHelper.java
===================================================================
--- src/java/org/apache/lucene/util/StringHelper.java	(revision 766478)
+++ src/java/org/apache/lucene/util/StringHelper.java	(working copy)
@@ -24,7 +24,9 @@
  * $Id$
  */
 public abstract class StringHelper {
+  public static StringInterner interner = new SimpleStringInterner(32);
 
+
   /**
    * Compares two byte[] arrays, element by element, and returns the
    * number of elements common to both arrays.
Index: src/java/org/apache/lucene/util/StringInterner.java
===================================================================
--- src/java/org/apache/lucene/util/StringInterner.java	(revision 0)
+++ src/java/org/apache/lucene/util/StringInterner.java	(revision 0)
@@ -0,0 +1,29 @@
+package org.apache.lucene.util;
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+public class StringInterner {
+  /** interns a string according to this StringCreator instance. */
+  public String intern(String s) {
+    return s.intern();
+  }
+
+  /** interns a string according to this StringCreator instance. */  
+  public String intern(char[] arr, int offset, int len) {
+    return intern(new String(arr, offset, len));
+  }
+}

Property changes on: src/java/org/apache/lucene/util/StringInterner.java
___________________________________________________________________
Added: svn:executable
   + *
Added: svn:keywords
   + Date Author Id Revision HeadURL
Added: svn:eol-style
   + native

Index: src/java/org/apache/lucene/util/SimpleStringInterner.java
===================================================================
--- src/java/org/apache/lucene/util/SimpleStringInterner.java	(revision 0)
+++ src/java/org/apache/lucene/util/SimpleStringInterner.java	(revision 0)
@@ -0,0 +1,107 @@
+package org.apache.lucene.util;
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+
+/**
+ * Simple lockless and memory barrier free String intern cache that is guaranteed
+ * to return the same String instance as String.intern() does.
+ */
+public class SimpleStringInterner extends StringInterner {
+  private String[] cache;
+  int numEntries;
+
+  public SimpleStringInterner(int sz) {
+    cache = new String[BitUtil.nextHighestPowerOfTwo(sz)];
+  }
+
+  private String add(String s) {
+    synchronized(this) {
+      numEntries++;
+      // check if we are over the load factor of 75%
+      if (numEntries+(numEntries>>2) > cache.length) {
+        int newSz = cache.length<<1;
+        String[] newArr = new String[newSz];
+        for (int i=0; i<cache.length; i++) {
+          String ss = cache[i];
+          if (ss == null) continue;
+          int h = ss.hashCode();
+          int slot = h & (newArr.length-1);
+          while (newArr[slot]!=null) {
+            slot = (slot + ((h>>7)|1)) & (newArr.length-1);
+          }
+          newArr[slot] = ss;
+        }
+
+        // publish new cache... lack of read barriers by readers may
+        // cause false misses, but this is OK.
+        cache = newArr;
+      }
+
+      // find the correct spot for the new String, keeping in
+      // mind that we may have already added it.
+      int h = s.hashCode();
+      int slot = h & (cache.length-1);
+      for(;;) {
+        String ss = cache[slot];
+        if (ss==null) {
+          // a new string... intern it first.
+          s = s.intern();
+          cache[slot] = s;
+          return s;
+        }
+        if (h==ss.hashCode() && s.compareTo(ss)==0) {
+          // this string was already added.
+          numEntries--;
+          return ss;
+        }
+        slot = (slot + ((h>>7)|1)) & (cache.length-1);
+      }
+    }
+  }
+
+  // @Override
+  public String intern(String s) {
+    // grab the latest visible reference and then only use that the rest
+    // of the time for consistency.
+    String[] arr = cache;
+
+    int h = s.hashCode();
+    int slot = h & (arr.length-1);
+
+    for (;;) {
+      String other = arr[slot];
+      if (other==null) {
+        // cache miss... insert it.
+        return add(s);
+      }
+
+      // check cached hashCode first, and use compareTo to avoid
+      // dynamic type checking in equals().
+      if (h == other.hashCode() && s.compareTo(other)==0) {
+        return s;
+      }
+
+      // Adding an odd number to this power-of-two hash table is
+      // guaranteed to do a full traversal, so instead of re-hashing
+      // we jump straight to a "linear" traversal, but base the step size
+      // on the hash code for better dispersion.  We don't use the lowest
+      // bits since they are ones that resulted in a collision.
+      slot = (slot + ((h>>7)|1)) & (arr.length-1);
+    }
+  }
+}
\ No newline at end of file

Property changes on: src/java/org/apache/lucene/util/SimpleStringInterner.java
___________________________________________________________________
Added: svn:executable
   + *
Added: svn:keywords
   + Date Author Id Revision HeadURL
Added: svn:eol-style
   + native

