Skip to content

Commit 00d7ba7

Browse files
committed
fix race condition
1 parent 78e83da commit 00d7ba7

3 files changed

Lines changed: 50 additions & 5 deletions

File tree

src/FastCloner.Tests/ConcurrentTests.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
using System.Collections.Concurrent;
22
using FastCloner.Code;
3-
using System.Threading.Tasks;
43

54
namespace FastCloner.Tests;
5+
6+
[NotInParallel("FastClonerGlobalState")]
67
public class ConcurrentTests(int maxRecursionDepth) : BaseTestFixture(maxRecursionDepth)
78
{
89
private class TestClass

src/FastCloner.Tests/TypeBehaviorTests.cs

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -825,21 +825,46 @@ public async Task GlobalConfigPublish_BumpsCacheVersion_ForSubsequentReaders()
825825
};
826826

827827
long startingVersion = FastClonerCache.GetCacheVersion();
828-
829-
FastCloner.MaxRecursionDepth = 999;
828+
829+
FastCloner.SetTypeBehavior<int>(CloneBehavior.Reference);
830830
_ = simple.DeepClone();
831831
_ = dictionary.DeepClone();
832832

833833
long firstMutationVersion = FastClonerCache.GetCacheVersion();
834834
await Assert.That(firstMutationVersion).IsGreaterThan(startingVersion);
835835

836-
FastCloner.MaxRecursionDepth = 998;
836+
FastCloner.ClearTypeBehavior<int>();
837837
_ = simple.DeepClone();
838838
_ = dictionary.DeepClone();
839839

840840
await Assert.That(FastClonerCache.GetCacheVersion()).IsGreaterThan(firstMutationVersion);
841841
}
842842

843+
[Test]
844+
public async Task MaxRecursionDepth_Update_Does_Not_Bump_Cache_Version()
845+
{
846+
FastCloner.ClearCache();
847+
FastCloner.ClearAllTypeBehaviors();
848+
FastCloner.SetDisableOptionalFeatures(false);
849+
850+
SimpleClass simple = new SimpleClass { IntValue = 7, StringValue = "Seven" };
851+
_ = simple.DeepClone();
852+
853+
long versionBefore = FastClonerCache.GetCacheVersion();
854+
855+
FastCloner.MaxRecursionDepth = 999;
856+
SimpleClass clone1 = simple.DeepClone();
857+
858+
FastCloner.MaxRecursionDepth = 998;
859+
SimpleClass clone2 = simple.DeepClone();
860+
861+
await Assert.That(FastClonerCache.GetCacheVersion()).IsEqualTo(versionBefore);
862+
await Assert.That(clone1.IntValue).IsEqualTo(7);
863+
await Assert.That(clone2.IntValue).IsEqualTo(7);
864+
865+
FastCloner.MaxRecursionDepth = 1_000;
866+
}
867+
843868
[Test]
844869
public async Task RuntimeConfig_Create_DefaultValues_CanStaySingletonOrBecomeDistinctSnapshot()
845870
{

src/FastCloner/FastCloner.cs

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ public static int MaxRecursionDepth
4545
if (maxRecursionDepth == value)
4646
return;
4747

48-
PublishEngine(CreatePublishedEngine(value, disableOptionalFeatures, GetTypeBehaviors()));
48+
PublishMaxRecursionDepth(value);
4949
}
5050
}
5151
}
@@ -197,6 +197,25 @@ private static void PublishEngine(FastClonerPublishedEngine engine)
197197
FastClonerCache.ClearCache();
198198
Volatile.Write(ref publishedEngine, engine);
199199
}
200+
201+
private static void PublishMaxRecursionDepth(int value)
202+
{
203+
FastClonerPublishedEngine current = Volatile.Read(ref publishedEngine);
204+
FastClonerRuntimeConfig oldConfig = current.RuntimeConfig;
205+
FastClonerRuntimeConfig newConfig = FastClonerRuntimeConfig.Create(
206+
value,
207+
oldConfig.DisableOptionalFeatures,
208+
oldConfig.CloneTypeBehaviors(),
209+
oldConfig.CacheKey,
210+
useStartupDefaultSingleton: true);
211+
212+
FastClonerPublishedEngine newEngine = ReferenceEquals(newConfig, FastClonerRuntimeConfig.Default)
213+
? FastClonerPublishedEngine.StartupDefault
214+
: FastClonerPublishedEngine.CreateConfigured(newConfig);
215+
216+
maxRecursionDepth = value;
217+
Volatile.Write(ref publishedEngine, newEngine);
218+
}
200219

201220
private static FastClonerPublishedEngine CreatePublishedEngine(
202221
int maxRecursionDepth,

0 commit comments

Comments
 (0)