internal void with_result_multiple_threads(string dbgWayToCallDesc, Func <LazyContextualInit <string>, Func <string>, string> wayToCall) { var counter = new ThreadSafeIntCounter(); var lazyCtxInit = new LazyContextualInit <string>(); var threadResults = MultiThreadsTestUtils.TestOnThreads(threadIndex => wayToCall(lazyCtxInit, () => counter.Increment().ToString())); lazyCtxInit.IsInited.Should().BeTrue($"{nameof(dbgWayToCallDesc)}: {dbgWayToCallDesc}"); counter.Value.Should().Be(1); threadResults.ForEach(x => x.Should().Be("1")); }
internal void no_result_multiple_threads(string dbgWayToCallDesc, Func <LazyContextualInit, Action, bool> wayToCall) { var counter = new ThreadSafeIntCounter(); var lazyCtxInit = new LazyContextualInit(); var threadResults = MultiThreadsTestUtils.TestOnThreads(threadIndex => wayToCall(lazyCtxInit, () => counter.Increment())); lazyCtxInit.IsInited.Should().BeTrue($"{nameof(dbgWayToCallDesc)}: {dbgWayToCallDesc}"); counter.Value.Should().Be(1); threadResults.Where(isInitedByThisCall => isInitedByThisCall).Should().ContainSingle(); threadResults.Where(isInitedByThisCall => !isInitedByThisCall).Should().HaveCount(threadResults.Count - 1); }
internal void InitializedOnlyOnceFromMultipleThreads(string dbgWayToCallDesc, Func <LazyContextualInit <string>, Func <string>, string> wayToCall) { var counter = new ThreadSafeCounter(); var ctxLazy = new LazyContextualInit <string>(); var numberOfThreads = Math.Max(Environment.ProcessorCount, 2); var threadIndexesAndValues = new ConcurrentBag <ValueTuple <int, string> >(); var barrier = new Barrier(numberOfThreads); var expectedThreadIndexes = Enumerable.Range(1, numberOfThreads); var threads = expectedThreadIndexes.Select(i => new Thread(() => EachThreadDo(i))).ToList(); foreach (var thread in threads) { thread.Start(); } foreach (var thread in threads) { thread.Join(); } ctxLazy.IsInited.Should().BeTrue($"{nameof(dbgWayToCallDesc)}: {dbgWayToCallDesc}"); counter.Value.Should().Be(1); threadIndexesAndValues.Should().HaveCount(numberOfThreads); var actualThreadIndexes = new HashSet <int>(); foreach (var(threadIndex, value) in threadIndexesAndValues) { value.Should().Be("1"); actualThreadIndexes.Add(threadIndex); } actualThreadIndexes.Should().HaveCount(numberOfThreads); foreach (var expectedThreadIndex in expectedThreadIndexes) { actualThreadIndexes.Should().Contain(expectedThreadIndex); } void EachThreadDo(int threadIndex) { barrier.SignalAndWait(); var value = wayToCall(ctxLazy, () => counter.Increment().ToString()); threadIndexesAndValues.Add((threadIndex, value)); } }
internal void InitializedOnlyOnceOnFirstAccess(string dbgWayToCallDesc, Func <LazyContextualInit <string>, Func <string>, string> wayToCall) { var counter = new ThreadSafeCounter(); var ctxLazy = new LazyContextualInit <string>(); ctxLazy.IsInited.Should().BeFalse(); ctxLazy.IfNotInited.Should().NotBeNull(); var val1 = wayToCall(ctxLazy, () => counter.Increment().ToString()); ctxLazy.IsInited.Should().BeTrue($"{nameof(dbgWayToCallDesc)}: {dbgWayToCallDesc}"); ctxLazy.IfNotInited.Should().BeNull(); val1.Should().Be("1"); counter.Value.Should().Be(1); var val2 = wayToCall(ctxLazy, () => counter.Increment().ToString()); ctxLazy.IsInited.Should().BeTrue(); val2.Should().Be("1"); counter.Value.Should().Be(1); }
internal void no_result_initialized_only_once_on_first_call(string dbgWayToCallDesc, Func <LazyContextualInit, Action, bool> wayToCall) { var counter = new ThreadSafeIntCounter(); var lazyCtxInit = new LazyContextualInit(); lazyCtxInit.IsInited.Should().BeFalse(); lazyCtxInit.IfNotInited.Should().NotBeNull(); var isInitedByThisCall = wayToCall(lazyCtxInit, () => counter.Increment()); isInitedByThisCall.Should().BeTrue($"{nameof(dbgWayToCallDesc)}: {dbgWayToCallDesc}"); lazyCtxInit.IsInited.Should().BeTrue(); lazyCtxInit.IfNotInited.Should().BeNull(); counter.Value.Should().Be(1); isInitedByThisCall = wayToCall(lazyCtxInit, () => counter.Increment()); isInitedByThisCall.Should().BeFalse($"{nameof(dbgWayToCallDesc)}: {dbgWayToCallDesc}"); lazyCtxInit.IsInited.Should().BeTrue(); counter.Value.Should().Be(1); }
internal void with_result_initialized_only_once_on_first_call(string dbgWayToCallDesc , Func <LazyContextualInit <string>, Func <string>, string> wayToCall) { var counter = new ThreadSafeIntCounter(); var lazyCtxInit = new LazyContextualInit <string>(); lazyCtxInit.IsInited.Should().BeFalse(); lazyCtxInit.IfNotInited.Should().NotBeNull(); var val1 = wayToCall(lazyCtxInit, () => counter.Increment().ToString()); lazyCtxInit.IsInited.Should().BeTrue($"{nameof(dbgWayToCallDesc)}: {dbgWayToCallDesc}"); lazyCtxInit.IfNotInited.Should().BeNull(); val1.Should().Be("1"); counter.Value.Should().Be(1); var val2 = wayToCall(lazyCtxInit, () => counter.Increment().ToString()); lazyCtxInit.IsInited.Should().BeTrue(); val2.Should().Be("1"); counter.Value.Should().Be(1); }
internal IfNotInitedHelper(LazyContextualInit owner) => _owner = owner;