You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucenenet.apache.org by mh...@apache.org on 2014/08/14 03:22:27 UTC
[5/5] git commit: adding SetOnce with tests.
adding SetOnce<T> with tests.
Project: http://git-wip-us.apache.org/repos/asf/lucenenet/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucenenet/commit/7cfd98d5
Tree: http://git-wip-us.apache.org/repos/asf/lucenenet/tree/7cfd98d5
Diff: http://git-wip-us.apache.org/repos/asf/lucenenet/diff/7cfd98d5
Branch: refs/heads/pcl
Commit: 7cfd98d54732c0f5c4a17dc2121c3eb6b3b22dc4
Parents: 8ad0c83
Author: Michael Herndon <mh...@michaelherndon.com>
Authored: Wed Aug 13 21:21:03 2014 -0400
Committer: Michael Herndon <mh...@michaelherndon.com>
Committed: Wed Aug 13 21:21:03 2014 -0400
----------------------------------------------------------------------
src/Lucene.Net.Core/Lucene.Net.Core.csproj | 1 +
src/Lucene.Net.Core/Util/BroadWord.cs | 7 +-
src/Lucene.Net.Core/Util/CharsRef.cs | 6 +-
src/Lucene.Net.Core/Util/SetOnce.cs | 102 +++++++++++++++
.../Lucene.Net.Core.Tests.csproj | 1 +
test/Lucene.Net.Core.Tests/Util/TestSetOnce.cs | 126 +++++++++++++++++++
6 files changed, 239 insertions(+), 4 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/7cfd98d5/src/Lucene.Net.Core/Lucene.Net.Core.csproj
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Core/Lucene.Net.Core.csproj b/src/Lucene.Net.Core/Lucene.Net.Core.csproj
index 64dfeb9..75c8337 100644
--- a/src/Lucene.Net.Core/Lucene.Net.Core.csproj
+++ b/src/Lucene.Net.Core/Lucene.Net.Core.csproj
@@ -82,6 +82,7 @@
<Compile Include="Util\IBits.cs" />
<Compile Include="Util\InPlaceMergeSorter.cs" />
<Compile Include="Util\RamUsageEstimator.cs" />
+ <Compile Include="Util\SetOnce.cs" />
<Compile Include="Util\Sorter.cs" />
<Compile Include="Util\StringHelper.cs" />
<Compile Include="Util\SystemProps.cs" />
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/7cfd98d5/src/Lucene.Net.Core/Util/BroadWord.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Core/Util/BroadWord.cs b/src/Lucene.Net.Core/Util/BroadWord.cs
index 1fa2f36..b73a68c 100644
--- a/src/Lucene.Net.Core/Util/BroadWord.cs
+++ b/src/Lucene.Net.Core/Util/BroadWord.cs
@@ -151,9 +151,14 @@ namespace Lucene.Net.Util
/// <summary>
- /// Naive implementation of <seealso cref="#select(long,int)"/>, using <seealso cref="Long#numberOfTrailingZeros"/> repetitively.
+ /// Naive implementation of <seealso cref="Select(long,int)"/>.
/// Works relatively fast for low ranks.
/// </summary>
+ /// <remarks>
+ /// <para>
+ /// Internally uses <see cref="Lucene.Net.Support.NumberExtensionMethods.NumberOfTrailingZeros"/> repetitively.
+ /// </para>
+ /// </remarks>
/// <returns> The index of the r-th 1 bit in x, or if no such bit exists, 72. </returns>
public static int SelectNaive(long x, int r)
{
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/7cfd98d5/src/Lucene.Net.Core/Util/CharsRef.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Core/Util/CharsRef.cs b/src/Lucene.Net.Core/Util/CharsRef.cs
index 744db7b..02afe39 100644
--- a/src/Lucene.Net.Core/Util/CharsRef.cs
+++ b/src/Lucene.Net.Core/Util/CharsRef.cs
@@ -152,10 +152,10 @@ namespace Lucene.Net.Util
}
/// <summary>
- ///
+ /// Determines if the other <see cref="CharsRef"/> is equal to the current instance.
/// </summary>
- /// <param name="other"></param>
- /// <returns></returns>
+ /// <param name="other">The instance to compare.</param>
+ /// <returns>True, if the other instance is equal to the current instance, otherwise false.</returns>
public bool CharsEquals(CharsRef other)
{
if (Length == other.Length)
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/7cfd98d5/src/Lucene.Net.Core/Util/SetOnce.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Core/Util/SetOnce.cs b/src/Lucene.Net.Core/Util/SetOnce.cs
new file mode 100644
index 0000000..ac3c821
--- /dev/null
+++ b/src/Lucene.Net.Core/Util/SetOnce.cs
@@ -0,0 +1,102 @@
+/*
+ * 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.
+ */
+
+namespace Lucene.Net.Util
+{
+ using System;
+ using Lucene.Net.Support;
+
+
+
+ /// <summary>
+ /// A convenient class which offers a semi-immutable object wrapper
+ /// implementation which allows one to set the value of an object exactly once,
+ /// and retrieve it many times.
+ /// </summary>
+ /// <typeparam name="T">The value type.</typeparam>
+ public class SetOnce<T> : Lucene.Net.Support.ICloneable
+ {
+ private T value;
+ private volatile bool isSet;
+
+ /// <summary>
+ /// Initializes a new instance of <see cref="SetOnce{T}"/>
+ /// </summary>
+ public SetOnce()
+ {
+ this.isSet = false;
+ }
+
+ /// <summary>
+ /// Initializes a new instance of <see cref="SetOnce{T}"/> with the
+ /// specified <paramref name="value"/>/
+ /// </summary>
+ /// <param name="value">The value to set.</param>
+ public SetOnce(T value)
+ {
+ this.Set(value);
+ }
+
+ /// <summary>
+ /// Gets whether or not the value is already set.
+ /// </summary>
+ public bool ValueIsSet
+ {
+ get { return this.isSet; }
+ }
+
+ /// <summary>
+ /// Gets or sets the value once.
+ /// </summary>
+ public T Value
+ {
+ get { return this.value; }
+ set { this.Set(value); }
+ }
+
+ /// <summary>
+ /// Sets the value.
+ /// </summary>
+ /// <param name="value">The value to be set.</param>
+ /// <exception cref="SetOnce.AlreadySetException">Thrown when the value has already been set.</exception>
+ protected void Set(T value)
+ {
+ if (!Object.ReferenceEquals(this.value, value) && isSet)
+ throw new AlreadySetException("value has already been set");
+
+ this.isSet = true;
+ this.value = value;
+ }
+
+ [Serializable]
+ public class AlreadySetException : Exception
+ {
+ public AlreadySetException() : this("The object cannot be set more than once.") { }
+ public AlreadySetException(string message) : base(message) { }
+ public AlreadySetException(string message, Exception inner) : base(message, inner) { }
+
+ }
+
+ public object Clone(bool deepClone)
+ {
+ if (deepClone)
+ throw new DeepCloneNotSupportedException();
+
+ return this.MemberwiseClone();
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/7cfd98d5/test/Lucene.Net.Core.Tests/Lucene.Net.Core.Tests.csproj
----------------------------------------------------------------------
diff --git a/test/Lucene.Net.Core.Tests/Lucene.Net.Core.Tests.csproj b/test/Lucene.Net.Core.Tests/Lucene.Net.Core.Tests.csproj
index 6a44bcd..8f6632f 100644
--- a/test/Lucene.Net.Core.Tests/Lucene.Net.Core.Tests.csproj
+++ b/test/Lucene.Net.Core.Tests/Lucene.Net.Core.Tests.csproj
@@ -68,6 +68,7 @@
<Compile Include="Util\TestConstants.cs" />
<Compile Include="Util\TestInPlaceMergeSorter.cs" />
<Compile Include="Util\TestRamEstimatorUsage.cs" />
+ <Compile Include="Util\TestSetOnce.cs" />
<Compile Include="Util\TestVersion.cs" />
</ItemGroup>
<ItemGroup>
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/7cfd98d5/test/Lucene.Net.Core.Tests/Util/TestSetOnce.cs
----------------------------------------------------------------------
diff --git a/test/Lucene.Net.Core.Tests/Util/TestSetOnce.cs b/test/Lucene.Net.Core.Tests/Util/TestSetOnce.cs
new file mode 100644
index 0000000..dcbd1e0
--- /dev/null
+++ b/test/Lucene.Net.Core.Tests/Util/TestSetOnce.cs
@@ -0,0 +1,126 @@
+/*
+ * 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.
+ */
+
+namespace Lucene.Net.Util
+{
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Text;
+ using System.Threading.Tasks;
+
+ public class TestSetOnce : LuceneTestCase
+ {
+ [Test(JavaMethodName = "TestEmptyCtor")]
+ public void Constructor()
+ {
+ var set = new SetOnce<int?>();
+ Equal(null, set.Value);
+ }
+
+ [Test(JavaMethodName = "TestSettingCtor")]
+ public void ConstructorWithValue()
+ {
+ var set = new SetOnce<int>(5);
+ Equal(5, set.Value);
+
+ Throws<SetOnce<int>.AlreadySetException>(() =>
+ {
+ set.Value = 7;
+ });
+ }
+
+ [Test]
+ public void TestSet()
+ {
+ var set = new SetOnce<int>();
+ Equal(0, set.Value);
+
+ set.Value = 5;
+ Equal(5, set.Value);
+
+ Throws<SetOnce<int>.AlreadySetException>(() =>
+ {
+ set.Value = 7;
+ });
+ }
+
+ [Test]
+ public void TestSetMultiThreaded()
+ {
+ // This test will always differ from the Java version
+ // because the Lucene.Net.Core project is now a PCL project.
+
+
+ var one = new SetOnce<int>();
+ Task<Result>[] tasks = new Task<Result>[10];
+ Result[] results = new Result[10];
+ tasks.Length.Times((i) =>
+ {
+ var result = new Result() {
+ Name = "Thread " + i.ToString(),
+ Value = i
+ };
+ results[i] = result;
+
+ tasks[i] = new Task<Result>(() => {
+
+
+ try {
+ one.Value = i;
+ result.Success = true;
+ result.Set = one;
+ } catch {
+ result.Set = one;
+ result.Success = false;
+ }
+
+ return result;
+ });
+ });
+
+ foreach (var task in tasks)
+ task.Start();
+
+ var final = Task.WhenAll(tasks).Result;
+
+ var successes = final.Where(o => o.Success).Count();
+
+ Ok(final.Count() == 10, "There should be 10 results.");
+ Ok(successes == 1, "There should be only one result that is a success.");
+
+ foreach(var task in tasks)
+ {
+ if(task.Result != null && task.Result.Success)
+ {
+ var expected = results[task.Result.Value];
+ Equal(expected.Value, task.Result.Set.Value);
+ }
+ }
+ }
+
+ public class Result
+ {
+ public string Name { get; set; }
+ public int Value { get; set; }
+
+ public bool Success { get; set; }
+
+ public SetOnce<int> Set { get; set; }
+ }
+ }
+}