internal static void CreateMutableResourceVaultTheCorrectWay() { var sbVault = MutableResourceVault <StringBuilder> .CreateAtomicMutableResourceVault(() => new StringBuilder(), TimeSpan.FromMilliseconds(250)); Console.WriteLine(@$ "We just created a [{sbVault}] in the correct way -- " + @"only the mutable resource vault will ever see the StringBuilder it constructs."); }
internal static void CreateMutableResourceVaultTheIncorrectWay() { var sbVault = MutableResourceVault <StringBuilder> .CreateAtomicMutableResourceVault(() => BadPreExistingStringBuilder, TimeSpan.FromMilliseconds(250)); Console.WriteLine( $@"We just created an [{sbVault}] in a very, very bad way. " + @"The vault now protects a resource that pre-existed the vault." + @$ " A change to {nameof(BadPreExistingStringBuilder)} is not thread-safe " + @"and will propagate to the vault's protected resource!"); }
public SimulationThread(int numActions, [NotNull] MutableResourceVault vault, [NotNull] LocklessStartSignal startSignal) { _numActions = numActions > 0 ? numActions : throw new ArgumentOutOfRangeException(nameof(numActions), numActions, @"Value must be positive."); _vault = vault ?? throw new ArgumentNullException(nameof(vault)); _started = startSignal ?? throw new ArgumentNullException(nameof(startSignal)); _thread = new Thread(ThreadLoop) { Name = $"StressTestThread_{Interlocked.Increment(ref _threadNo)}", IsBackground = false, Priority = ThreadPriority.Normal }; _thread.Start(_cts.Token); }
internal static void CreateMoreComplicatedMutableResourceTheCorrectWay() { var sbVault = MutableResourceVault <PrettyBadMoreComplexExample> .CreateAtomicMutableResourceVault(() => { var sbOne = new StringBuilder(); var sbTwo = new StringBuilder(); return(new PrettyBadMoreComplexExample(sbOne, sbTwo)); }, TimeSpan.FromMilliseconds(250)); Console.WriteLine(@$ "I just created a more complicated {sbVault} in the correct way." + @" Neither the PrettyBadMoreComplexExample nor any of its subobjects are " + @"accessible outside the mutable resource vault."); }
public static void DemonstrateUseOfExtensionMethodsToSimplify() { const string methodName = nameof(DemonstrateUseOfExtensionMethodsToSimplify); Console.WriteLine(); Console.WriteLine($"Performing {methodName}..."); MutableResourceVault <StringBuilder> vault = CreateExampleVault(); using var lck = vault.SpinLock(); Console.WriteLine("Contents: {0}", lck.GetContents()); Console.WriteLine("First char: {0}", lck.GetCharAt(0)); //make second char uppercase E lck.SetCharAt(1, 'E'); Console.WriteLine("Changed to uppercase 'E': {0}", lck.GetContents()); Console.WriteLine(); }
internal static void CreateMoreComplicatedMutableResourceInASlightlySubtleIncorrectWay( StringBuilder shouldBeSecond) { var sbVault = MutableResourceVault <PrettyBadMoreComplexExample> .CreateAtomicMutableResourceVault(() => { var sbOne = new StringBuilder(); //VERY BAD! Any change to ShouldBeSecond (which is accessible outside the vault) //is not thread-safe //and will propagate to the value in the vault! return(new PrettyBadMoreComplexExample(sbOne, shouldBeSecond)); }, TimeSpan.FromMilliseconds(250)); Console.WriteLine(@$ "I just created a {sbVault} in a very unsafe but subtle way. " + @$ "If anyone changes the object referred to by {nameof(shouldBeSecond)}," + @"It will propagate in an unsafe way to the value protected by the vault."); }
public static void DemonstrateActions() { const string methodName = nameof(DemonstrateActions); Console.WriteLine(); Console.WriteLine($"Performing {methodName}..."); MutableResourceVault <StringBuilder> vault = CreateExampleVault(); using var lck = vault.SpinLock(); lck.ExecuteAction((ref StringBuilder res) => { for (int i = 0; i < res.Length; ++i) { char current = res[i]; if (char.IsLetter(current)) { res[i] = char.IsLower(current) ? char.ToUpper(current) : char.ToLower(current); } } }); string contents = lck.ExecuteQuery((in StringBuilder sb) => sb.ToString()); Console.WriteLine("Reversed Upper/Lower res: " + $"{contents}"); //now let's make every char at idx divisible by three change to q int divisibleBy = 3; lck.ExecuteAction((ref StringBuilder res, in int d) => { for (int i = 0; i < res.Length; ++i) { if (i % d == 0) { res[i] = 'q'; } } }, divisibleBy); contents = lck.ExecuteQuery((in StringBuilder sb) => sb.ToString()); Console.WriteLine($"Made chars at idx divisble by 3 q: " + $"[{contents}]"); Console.WriteLine(); }
public static void DemonstrateMixedOperations() { const string methodName = nameof(DemonstrateMixedOperations); Console.WriteLine(); Console.WriteLine($"Performing {methodName}..."); MutableResourceVault <StringBuilder> vault = CreateExampleVault(); using var lck = vault.SpinLock(); //Find the index of the first char equal to 'o' and insert //" it's magic oooh oooh! " after it. //return the index and the new contents. string insertMe = " it's magic oooh oooh! "; char queryLetter = 'o'; IndexAndVal res = lck.ExecuteMixedOperation( (ref StringBuilder sb, in char ql) => { int idx = -1; for (int i = 0; i < sb.Length; ++i) { if (sb[i] == ql) { idx = i; break; } } if (idx != -1) { sb.Insert(idx + 1, insertMe); } return(new IndexAndVal(sb.ToString(), idx)); }, queryLetter); Console.WriteLine($"New value: [{res.NewValue}], " + $"Index: [{res.Idx}]."); Console.WriteLine(); }
static void TestIllegalNotVsProtectable() { StringBuilder [] sb = { new StringBuilder("Hi"), new StringBuilder("Mon"), }; DateTime[] datesAndTimes = GenDateTime(10); ImmutableArray <StringBuilder> immutSb = sb.ToImmutableArray(); ImmutableArray <DateTime> immut = datesAndTimes.ToImmutableArray(); var wrapper = VsArrayWrapper <DateTime> .CreateArrayWrapper(datesAndTimes); // var wrapper2 = VsArrayWrapper<StringBuilder>.CreateArrayWrapper(sb); //NOT OK -- is "considered" vault safe but isn't allowed as a protected resource //BasicVault<VsArrayWrapper<DateTime>> v = new BasicVault<VsArrayWrapper<DateTime>>(wrapper); //Ok -- ImmutableArray<DateTime> is vault safe //BasicVault<ImmutableArray<DateTime>> v = new BasicVault<ImmutableArray<DateTime>>(immut); //ok resource is not vault safe but mutresv doesnt require it MutableResourceVault <ImmutableArray <StringBuilder> > b = MutableResourceVault <ImmutableArray <StringBuilder> > .CreateAtomicMutableResourceVault( () => immutSb.ToImmutableArray(), TimeSpan.FromSeconds(2));
public static void ShowWrapperUsage() { Console.WriteLine("Begin showing wrapper usage."); MutableResourceVault <List <int> > vault = MutableResourceVault <List <int> > .CreateAtomicMutableResourceVault(() => new List <int> { 1, 2, 3, 4 }, TimeSpan.FromMilliseconds(250)); ImmutableArray <int> finalContents; { using var lck = vault.SpinLock(); List <int> addUs = new List <int> { 5, 6, 7, 8 }; //ERROR DotNetVault_VsDelegateCapture cannot capute non-vault //safe param addUs, of type List, not vault-safe //lck.ExecuteAction((ref List<int> res) => res.AddRange(addUs)); //Ok reference is to thin readonly wrapper around list of vault-safe type. //state cannot be commingled in the delegate. VsListWrapper <int> wrapper = VsListWrapper <int> .FromList(addUs); lck.ExecuteAction((ref List <int> res) => res.AddRange(wrapper)); finalContents = lck.ExecuteQuery((in List <int> res) => res.ToImmutableArray()); } Console.WriteLine("Printing final contents: "); StringBuilder sb = new StringBuilder("{"); foreach (var i in finalContents) { sb.Append($"{i}, "); } if (sb[^ 1] == ' ' && sb[^ 2] == ',')
public static void DemonstrateQueries() { const string methodName = nameof(DemonstrateQueries); Console.WriteLine(); Console.WriteLine($"Performing {methodName}..."); MutableResourceVault <StringBuilder> vault = CreateExampleVault(); using var lck = vault.SpinLock(); string contents = lck.ExecuteQuery((in StringBuilder res) => res.ToString()); Console.WriteLine($"Contents: {contents}."); int ancillaryValue = 7; int lengthPlusAncillaryValue = lck.ExecuteQuery((in StringBuilder sb, in int anc) => sb.Length + anc, ancillaryValue); Console.WriteLine("Length of contents (content length: " + $"[{lck.ExecuteQuery( (in StringBuilder sb) => sb.Length)}]) " + $"plus [{nameof(ancillaryValue)}] of [{ancillaryValue}]: " + $"{lengthPlusAncillaryValue.ToString()}"); int idx = 1; char offSet = (char)32; char valOfCharSpecifiedIndexMadeUppercase = lck.ExecuteQuery( (in StringBuilder sb, in char offset) => (char)(sb[idx] - offSet), offSet); Console.WriteLine($"Char at idx [{idx.ToString()}] " + $"(current val: [{contents[1]}]) made upper " + $"case: [{valOfCharSpecifiedIndexMadeUppercase}]."); Console.WriteLine(); Console.WriteLine("Bug50Demo3 START"); Bug50Demo3(); Console.WriteLine("Bug50Demo3 END"); }
private static MutableResourceVault <StringBuilder> CreateExampleVault() => MutableResourceVault <StringBuilder> .CreateAtomicMutableResourceVault(() => new StringBuilder("Hello, world!"), TimeSpan.FromMilliseconds(250));
internal static MutableResourceVault <StringBuilder> CreateMutableResourceVault() => MutableResourceVault <StringBuilder> .CreateAtomicMutableResourceVault(() => new StringBuilder(), TimeSpan.FromMilliseconds(100));