public void RemoveTest() { var dict = new ShieldedDict <string, object>(new KeyValuePair <string, object>[] { new KeyValuePair <string, object>("key a", null), new KeyValuePair <string, object>("key b", null), new KeyValuePair <string, object>("key c", null), }); Assert.Throws <InvalidOperationException>(() => dict.Remove("key a")); Assert.Throws <InvalidOperationException>(() => ((ICollection <KeyValuePair <string, object> >)dict).Remove( new KeyValuePair <string, object>("key a", null))); Shield.InTransaction(() => { dict.Remove("key a"); Assert.AreEqual(2, dict.Count); Assert.IsFalse(dict.ContainsKey("key a")); }); Assert.AreEqual(2, dict.Count); Assert.IsFalse(dict.ContainsKey("key a")); Shield.InTransaction(() => { ((ICollection <KeyValuePair <string, object> >)dict).Remove( new KeyValuePair <string, object>("key b", null)); Assert.AreEqual(1, dict.Count); Assert.IsFalse(dict.ContainsKey("key b")); }); Assert.AreEqual(1, dict.Count); Assert.IsFalse(dict.ContainsKey("key b")); // ToList() avoids the need for a transaction, usually needed for enumerating collections. Assert.AreEqual("key c", dict.ToList().Single().Key); }
public void ContainsTest() { var dict = new ShieldedDict <string, object>(new KeyValuePair <string, object>[] { new KeyValuePair <string, object>("key a", null), new KeyValuePair <string, object>("key b", null), new KeyValuePair <string, object>("key c", null), }); Assert.IsTrue(dict.ContainsKey("key a")); Assert.IsTrue(((ICollection <KeyValuePair <string, object> >)dict).Contains( new KeyValuePair <string, object>("key a", null))); Assert.IsFalse(dict.ContainsKey("not me")); Assert.IsFalse(((ICollection <KeyValuePair <string, object> >)dict).Contains( new KeyValuePair <string, object>("not me", null))); Shield.InTransaction(() => { dict.Add("new key", null); dict.Remove("key a"); Assert.IsFalse(dict.ContainsKey("key a")); Assert.IsFalse(((ICollection <KeyValuePair <string, object> >)dict).Contains( new KeyValuePair <string, object>("key a", null))); Assert.IsTrue(dict.ContainsKey("new key")); Assert.IsTrue(((ICollection <KeyValuePair <string, object> >)dict).Contains( new KeyValuePair <string, object>("new key", null))); }); }
public void EnumerationTest() { var ordinaryDict = new Dictionary <int, object>() { { 1, new object() }, { 101, new object() }, { 666999, new object() } }; var dict = new ShieldedDict <int, object>(ordinaryDict); var addedObject = new object(); // in preparation for the same changes done to dict inside transaction ordinaryDict.Add(2, addedObject); ordinaryDict.Remove(666999); Shield.InTransaction(() => { // as an IShielded implementor, the Dict is more complex and needs to be more carefully // tested for how well he manages thread-local data. So, we add some changes here. dict.Add(2, addedObject); dict.Remove(666999); int count = 0; var checkSet = new HashSet <int>(); foreach (var kvp in dict) { Assert.IsTrue(checkSet.Add(kvp.Key)); Assert.IsTrue(ordinaryDict.ContainsKey(kvp.Key)); Assert.AreEqual(ordinaryDict[kvp.Key], kvp.Value); count++; } Assert.AreEqual(3, count); }); }
public void EnumerationTest() { var ordinaryDict = new Dictionary <int, object>() { { 1, new object() }, { 101, new object() }, { 666999, new object() } }; var dict = new ShieldedDict <int, object>(ordinaryDict); var addedObject = new object(); // in preparation for the same changes done to dict inside transaction ordinaryDict.Add(2, addedObject); ordinaryDict.Remove(666999); Shield.InTransaction(() => { // as an IShielded implementor, the Dict is more complex and needs to be more carefully // tested for how well he manages thread-local data. So, we add some changes here. dict.Add(2, addedObject); dict.Remove(666999); Assert.IsTrue(dict.OrderBy(kvp => kvp.Key).SequenceEqual(ordinaryDict.OrderBy(kvp => kvp.Key))); }); }
private static void DictionaryTest() { ShieldedDict<int, Shielded<int>> dict = new ShieldedDict<int, Shielded<int>>(); var randomizr = new Random(); foreach (var _ in Enumerable.Repeat(0, 10)) { var transactionCounter = 0; var time = mtTest("dictionary", 10000, i => { var rnd = randomizr.Next(10); if (i % 2 == 0) // adder task - 500 of these return Task.Factory.StartNew(() => { Shield.InTransaction(() => { Interlocked.Increment(ref transactionCounter); var v = dict.ContainsKey(rnd) ? dict[rnd] : null; int? num = v != null ? (int?)v.Read : null; Thread.Sleep(1); if (v == null) dict[rnd] = new Shielded<int>(1); else if (v.Read == -1) dict.Remove(rnd); else v.Modify((ref int a) => a = num.Value + 1); } ); }, TaskCreationOptions.LongRunning ); else // subtractor task - 500 of these return Task.Factory.StartNew(() => { Shield.InTransaction(() => { Interlocked.Increment(ref transactionCounter); var v = dict.ContainsKey(rnd) ? dict[rnd] : null; int? num = v != null ? (int?)v.Read : null; Thread.Sleep(1); if (v == null) dict[rnd] = new Shielded<int>(-1); else if (v.Read == 1) dict.Remove(rnd); else v.Modify((ref int a) => a = num.Value - 1); } ); }, TaskCreationOptions.LongRunning ); }); var sum = Enumerable.Range(0, 10).Sum(n => dict.ContainsKey(n) ? dict[n] : 0); Console.WriteLine(" {0} ms with {1} iterations and sum {2}.", time, transactionCounter, sum); } }
public void RemoveTest() { var dict = new ShieldedDict<string, object>(new KeyValuePair<string, object>[] { new KeyValuePair<string, object>("key a", null), new KeyValuePair<string, object>("key b", null), new KeyValuePair<string, object>("key c", null), }); Assert.Throws<InvalidOperationException>(() => dict.Remove("key a")); Assert.Throws<InvalidOperationException>(() => ((ICollection<KeyValuePair<string, object>>)dict).Remove( new KeyValuePair<string, object>("key a", null))); Shield.InTransaction(() => { dict.Remove("key a"); Assert.AreEqual(2, dict.Count); Assert.IsFalse(dict.ContainsKey("key a")); }); Assert.AreEqual(2, dict.Count); Assert.IsFalse(dict.ContainsKey("key a")); Shield.InTransaction(() => { ((ICollection<KeyValuePair<string, object>>)dict).Remove( new KeyValuePair<string, object>("key b", null)); Assert.AreEqual(1, dict.Count); Assert.IsFalse(dict.ContainsKey("key b")); }); Assert.AreEqual(1, dict.Count); Assert.IsFalse(dict.ContainsKey("key b")); // ToList() avoids the need for a transaction, usually needed for enumerating collections. Assert.AreEqual("key c", dict.ToList().Single().Key); }
public void EnumerationTest() { var ordinaryDict = new Dictionary<int, object>() { { 1, new object() }, { 101, new object() }, { 666999, new object() } }; var dict = new ShieldedDict<int, object>(ordinaryDict); var addedObject = new object(); // in preparation for the same changes done to dict inside transaction ordinaryDict.Add(2, addedObject); ordinaryDict.Remove(666999); Shield.InTransaction(() => { // as an IShielded implementor, the Dict is more complex and needs to be more carefully // tested for how well he manages thread-local data. So, we add some changes here. dict.Add(2, addedObject); dict.Remove(666999); int count = 0; var checkSet = new HashSet<int>(); foreach (var kvp in dict) { Assert.IsTrue(checkSet.Add(kvp.Key)); Assert.IsTrue(ordinaryDict.ContainsKey(kvp.Key)); Assert.AreEqual(ordinaryDict[kvp.Key], kvp.Value); count++; } Assert.AreEqual(3, count); }); }
public void ContainsTest() { var dict = new ShieldedDict<string, object>(new KeyValuePair<string, object>[] { new KeyValuePair<string, object>("key a", null), new KeyValuePair<string, object>("key b", null), new KeyValuePair<string, object>("key c", null), }); Assert.IsTrue(dict.ContainsKey("key a")); Assert.IsTrue(((ICollection<KeyValuePair<string, object>>)dict).Contains( new KeyValuePair<string, object>("key a", null))); Assert.IsFalse(dict.ContainsKey("not me")); Assert.IsFalse(((ICollection<KeyValuePair<string, object>>)dict).Contains( new KeyValuePair<string, object>("not me", null))); Shield.InTransaction(() => { dict.Add("new key", null); dict.Remove("key a"); Assert.IsFalse(dict.ContainsKey("key a")); Assert.IsFalse(((ICollection<KeyValuePair<string, object>>)dict).Contains( new KeyValuePair<string, object>("key a", null))); Assert.IsTrue(dict.ContainsKey("new key")); Assert.IsTrue(((ICollection<KeyValuePair<string, object>>)dict).Contains( new KeyValuePair<string, object>("new key", null))); }); }
public void DictionaryAccessExpandingTest() { var d = new ShieldedDict<int, object>(); // various combinations - one key is either written or just read, and the // WhenCommitting sub tries to mess with another key, or to promote the // read key. Shield.InTransaction(() => { d[1] = new object(); d[2] = new object(); }); // WhenCommitting does not fire unless at least something changed, so we need this Shielded<int> x = new Shielded<int>(); // reader promotion to writer not allowed using (Shield.WhenCommitting(fs => d[2] = new object())) { Assert.Throws<InvalidOperationException>(() => Shield.InTransaction(() => { x.Value = 1; var obj = d[2]; })); } // new read not allowed using (Shield.WhenCommitting(fs => { var obj = d[2]; })) { Assert.Throws<InvalidOperationException>(() => Shield.InTransaction(() => { x.Value = 1; var obj = d[1]; })); } // new write not allowed using (Shield.WhenCommitting(fs => d[2] = new object())) { Assert.Throws<InvalidOperationException>(() => Shield.InTransaction(() => { x.Value = 1; var obj = d[1]; })); } // same checks, but in situations when we did a write in the dict using (Shield.WhenCommitting(fs => d[2] = new object())) { Assert.Throws<InvalidOperationException>(() => Shield.InTransaction(() => { d[1] = new object(); var obj = d[2]; })); } using (Shield.WhenCommitting(fs => { var obj = d[2]; })) { Assert.Throws<InvalidOperationException>(() => Shield.InTransaction(() => { d[1] = new object(); })); } using (Shield.WhenCommitting(fs => d[2] = new object())) { Assert.Throws<InvalidOperationException>(() => Shield.InTransaction(() => { d[1] = new object(); })); } // removing should likewise be restricted using (Shield.WhenCommitting(fs => { d.Remove(1); Assert.Throws<InvalidOperationException>( () => d.Remove(2)); })) { Shield.InTransaction(() => { d[1] = new object(); }); } // the exception was caught, and the WhenCommiting delegate committed Assert.IsFalse(d.ContainsKey(1)); Shield.InTransaction(() => d[1] = new object()); // finally, something allowed - reading from read or written, and writing into written using (Shield.WhenCommitting(fs => { var obj = d[1]; var obj2 = d[2]; d[2] = new object(); })) { Shield.InTransaction(() => { var obj = d[1]; d[2] = new object(); }); } }
public void DictionaryAccessExpandingTest() { var d = new ShieldedDict <int, object>(); // various combinations - one key is either written or just read, and the // WhenCommitting sub tries to mess with another key, or to promote the // read key. Shield.InTransaction(() => { d[1] = new object(); d[2] = new object(); }); // WhenCommitting does not fire unless at least something changed, so we need this Shielded <int> x = new Shielded <int>(); // reader promotion to writer not allowed using (Shield.WhenCommitting(fs => d[2] = new object())) { Assert.Throws <AggregateException>(() => Shield.InTransaction(() => { x.Value = 1; var obj = d[2]; })); } // new read not allowed using (Shield.WhenCommitting(fs => { var obj = d[2]; })) { Assert.Throws <AggregateException>(() => Shield.InTransaction(() => { x.Value = 1; var obj = d[1]; })); } // new write not allowed using (Shield.WhenCommitting(fs => d[2] = new object())) { Assert.Throws <AggregateException>(() => Shield.InTransaction(() => { x.Value = 1; var obj = d[1]; })); } // same checks, but in situations when we did a write in the dict using (Shield.WhenCommitting(fs => d[2] = new object())) { Assert.Throws <AggregateException>(() => Shield.InTransaction(() => { d[1] = new object(); var obj = d[2]; })); } using (Shield.WhenCommitting(fs => { var obj = d[2]; })) { Assert.Throws <AggregateException>(() => Shield.InTransaction(() => { d[1] = new object(); })); } using (Shield.WhenCommitting(fs => d[2] = new object())) { Assert.Throws <AggregateException>(() => Shield.InTransaction(() => { d[1] = new object(); })); } // removing should likewise be restricted using (Shield.WhenCommitting(fs => { d.Remove(1); Assert.Throws <InvalidOperationException>( () => d.Remove(2)); })) { Shield.InTransaction(() => { d[1] = new object(); }); } // the exception was caught, and the WhenCommiting delegate committed Assert.IsFalse(d.ContainsKey(1)); Shield.InTransaction(() => d[1] = new object()); // finally, something allowed - reading from read or written, and writing into written using (Shield.WhenCommitting(fs => { var obj = d[1]; var obj2 = d[2]; d[2] = new object(); })) { Shield.InTransaction(() => { var obj = d[1]; d[2] = new object(); }); } }