示例#1
0
        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);
        }
示例#2
0
        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)));
            });
        }
示例#3
0
        public void BasicTest()
        {
            var dict = new ShieldedDict<int, object>();

            Assert.Throws<InvalidOperationException>(() =>
                dict[1] = new object());

            Shield.InTransaction(() =>
            {
                dict[2] = new object();
                // the TPL sometimes executes tasks on the same thread.
                object x1 = null;
                var t = new Thread(() =>
                {
                    Assert.IsFalse(Shield.IsInTransaction);
                    Assert.IsFalse(dict.ContainsKey(2));
                });
                t.Start();
                t.Join();

                Assert.IsNotNull(dict[2]);
            });

            object x2 = null;
            var t2 = new Thread(() =>
            {
                x2 = dict[2];
            });
            t2.Start();
            t2.Join();
            Assert.IsNotNull(x2);
            Assert.IsNotNull(dict[2]);
        }
示例#4
0
        public void EqualityComparerTest()
        {
            var dict = new ShieldedDict <int, object>(new OddsAndEvens());

            int    retryCount = 0;
            Thread oneTime    = null;

            Shield.InTransaction(() => {
                retryCount++;
                dict[1] = new object();
                dict[2] = new object();

                if (oneTime == null)
                {
                    oneTime = new Thread(() => {
                        Assert.IsFalse(Shield.IsInTransaction);
                        Assert.IsFalse(dict.ContainsKey(2));
                        Assert.IsFalse(dict.ContainsKey(4));
                        Shield.InTransaction(() => dict[4] = new object());
                    });
                    oneTime.Start();
                    oneTime.Join();
                }

                Assert.IsNotNull(dict[2]);
                Assert.IsNotNull(dict[4]);
                Assert.AreSame(dict[2], dict[4]);
                Assert.AreNotSame(dict[1], dict[2]);
            });
            Assert.AreEqual(2, retryCount);

            object x2 = null;
            var    t2 = new Thread(() => {
                x2 = dict[2];
                Assert.AreSame(dict[2], dict[4]);
                Assert.AreNotSame(dict[1], dict[2]);
            });

            t2.Start();
            t2.Join();
            Assert.IsNotNull(x2);
            Assert.IsNotNull(dict[2]);
            Assert.AreSame(dict[2], dict[4]);
            Assert.AreNotSame(dict[1], dict[2]);
        }
示例#5
0
        public void SimpleRace()
        {
            var dict = new ShieldedDict <int, int>();

            ParallelEnumerable.Range(0, 100000)
            .ForAll(i => Shield.InTransaction(
                        () => dict[i % 100] = dict.ContainsKey(i % 100) ? dict[i % 100] + 1 : 1));

            Shield.InTransaction(() => {
                for (int i = 0; i < 100; i++)
                {
                    Assert.AreEqual(1000, dict[i]);
                }
            });
        }
示例#6
0
        public void CopyToTest()
        {
            var dict = new ShieldedDict <int, object>(
                Enumerable.Range(1, 1000).Select(i =>
                                                 new KeyValuePair <int, object>(i, new object())).ToArray());

            Assert.AreEqual(1000, dict.Count);

            var array = new KeyValuePair <int, object> [1100];

            // this works out of transaction (and consequently, so do ToArray and ToList), by opening
            // a transaction itself. that could not be done when you do a foreach.
            ((ICollection <KeyValuePair <int, object> >)dict).CopyTo(array, 100);
            var keys = new HashSet <int>();

            foreach (var kvp in array.Skip(100))
            {
                Assert.IsTrue(dict.ContainsKey(kvp.Key));
                Assert.IsTrue(keys.Add(kvp.Key));
                Assert.AreEqual(dict[kvp.Key], kvp.Value);
            }
        }
示例#7
0
        public void BasicTest()
        {
            var dict = new ShieldedDict <int, object>();

            Assert.Throws <InvalidOperationException>(() =>
                                                      dict[1] = new object());

            bool detectable = false;

            using (Shield.WhenCommitting(dict, _ => detectable = true))
                Shield.InTransaction(() => dict[1] = new object());
            Assert.IsTrue(detectable);

            Shield.InTransaction(() =>
            {
                dict[2] = new object();
                // the TPL sometimes executes tasks on the same thread.
                var t = new Thread(() =>
                {
                    Assert.IsFalse(Shield.IsInTransaction);
                    Assert.IsFalse(dict.ContainsKey(2));
                });
                t.Start();
                t.Join();

                Assert.IsNotNull(dict[2]);
            });

            object x2 = null;
            var    t2 = new Thread(() =>
            {
                x2 = dict[2];
            });

            t2.Start();
            t2.Join();
            Assert.IsNotNull(x2);
            Assert.IsNotNull(dict[2]);
        }
示例#8
0
 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);
     }
 }
示例#9
0
        public void SimpleRace()
        {
            var dict = new ShieldedDict<int, int>();
            ParallelEnumerable.Range(0, 100000)
                .ForAll(i => Shield.InTransaction(
                    () => dict[i % 100] = dict.ContainsKey(i % 100) ? dict[i % 100] + 1 : 1));

            Shield.InTransaction(() => {
                for (int i = 0; i < 100; i++)
                    Assert.AreEqual(1000, dict[i]);
            });
        }
示例#10
0
        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);
        }
示例#11
0
        public void CopyToTest()
        {
            var dict = new ShieldedDict<int, object>(
                Enumerable.Range(1, 1000).Select(i =>
                    new KeyValuePair<int, object>(i, new object())).ToArray());
            Assert.AreEqual(1000, dict.Count);

            var array = new KeyValuePair<int, object>[1100];
            // this works out of transaction (and consequently, so do ToArray and ToList), by opening
            // a transaction itself. that could not be done when you do a foreach.
            ((ICollection<KeyValuePair<int, object>>)dict).CopyTo(array, 100);
            var keys = new HashSet<int>();
            foreach (var kvp in array.Skip(100))
            {
                Assert.IsTrue(dict.ContainsKey(kvp.Key));
                Assert.IsTrue(keys.Add(kvp.Key));
                Assert.AreEqual(dict[kvp.Key], kvp.Value);
            }
        }
示例#12
0
        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)));
            });
        }
示例#13
0
        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();
                });
            }
        }
示例#14
0
        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();
                });
            }
        }