예제 #1
0
    /// <summary>
    /// Runs all tests under each SyncBlk variation
    /// </summary>
    /// <param name="lockIsHeld">Whether to expect that the lock is being held (experiencing
    /// contention) while each lock attempt is performed</param>
    /// <param name="scenario">A lock contention scenario to run under each SyncBlk scenario.  Is
    /// passed an object that may or may not have a SyncBlk, and a lock acquisition scenario to run
    /// under that level of contention</param>
    void SyncBlkVariants(LockIsHeld lockIsHeld, Action <object, Action <object> > scenario)
    {
        Console.WriteLine("Positive tests, no SyncBlk");
        MethodVariants(lockIsHeld, delegate(Action <object> innerScenario)
        {
            object obj = new object();
            scenario(obj, delegate(object o) { innerScenario(o); });
        });

        Console.WriteLine("Positive tests, with HashCode");
        MethodVariants(lockIsHeld, delegate(Action <object> innerScenario)
        {
            object obj = new object();
            obj.GetHashCode();
            scenario(obj, delegate(object o) { innerScenario(o); });
        });

        Console.WriteLine("Positive tests, with SyncBlk");
        MethodVariants(lockIsHeld, delegate(Action <object> innerScenario)
        {
            object obj = new object();
            obj.GetHashCode();
            Monitor.Enter(obj);
            Monitor.Exit(obj);
            scenario(obj, delegate(object o) { innerScenario(o); });
        });
    }
예제 #2
0
    LockIsHeld Reverse(LockIsHeld lockIsHeld)
    {
        switch (lockIsHeld)
        {
        case LockIsHeld.Yes:
            return(LockIsHeld.No);

        case LockIsHeld.No:
            return(LockIsHeld.Yes);

        default:
            return(lockIsHeld);
        }
    }
예제 #3
0
    void AssertTookLockAndRelease(LockIsHeld expected, object obj, bool tookLock)
    {
        Assert((expected == LockIsHeld.Yes && tookLock) ||
               (expected == LockIsHeld.No && !tookLock) ||
               expected == LockIsHeld.Maybe);

        if (tookLock)
        {
            Assert(!inContention);
        }

        bool exitFailed = false;

        try
        {
            Monitor.Exit(obj);
        }
        catch (SynchronizationLockException)
        {
            exitFailed = true;
        }

        Assert(tookLock == !exitFailed);
    }
예제 #4
0
    /// <summary>
    /// Runs all lock acquisition scenarios inside of an outer contention/SyncBlk scenario
    /// </summary>
    /// <param name="lockIsHeld">whether to expect the lock to be held when we try to acquire it</param>
    /// <param name="scenario">The contention/SyncBlk scenario to run each acquisition scenario inside of.</param>
    void MethodVariants(LockIsHeld lockIsHeld, Action <Action <object> > scenario)
    {
        bool tookLock;

        scenario(delegate(object obj)
        {
            Monitor.Enter(obj);
            AssertTookLockAndRelease(LockIsHeld.Yes, obj, true);
        });

        scenario(delegate(object obj)
        {
            tookLock = false;
            Monitor.Enter(obj, ref tookLock);
            AssertTookLockAndRelease(LockIsHeld.Yes, obj, tookLock);
        });

        scenario(delegate(object obj)
        {
            tookLock = Monitor.TryEnter(obj);
            AssertTookLockAndRelease(Reverse(lockIsHeld), obj, tookLock);
        });

        scenario(delegate(object obj)
        {
            tookLock = Monitor.TryEnter(obj, 0);
            AssertTookLockAndRelease(Reverse(lockIsHeld), obj, tookLock);
        });

        scenario(delegate(object obj)
        {
            DateTime start = DateTime.Now;
            tookLock       = Monitor.TryEnter(obj, 10000);
            double elapsed = (DateTime.Now - start).TotalSeconds;
            AssertTookLockAndRelease(elapsed < 5.0 ? LockIsHeld.Yes : LockIsHeld.Maybe, obj, tookLock);
        });

        scenario(delegate(object obj)
        {
            tookLock = Monitor.TryEnter(obj, Timeout.Infinite);
            AssertTookLockAndRelease(LockIsHeld.Yes, obj, tookLock);
        });

        scenario(delegate(object obj)
        {
            tookLock = Monitor.TryEnter(obj, TimeSpan.FromMilliseconds(0));
            AssertTookLockAndRelease(Reverse(lockIsHeld), obj, tookLock);
        });

        scenario(delegate(object obj)
        {
            tookLock = Monitor.TryEnter(obj, TimeSpan.FromMilliseconds(10000));
            AssertTookLockAndRelease(LockIsHeld.Maybe, obj, tookLock);
        });

        scenario(delegate(object obj)
        {
            tookLock = Monitor.TryEnter(obj, TimeSpan.FromMilliseconds(Timeout.Infinite));
            AssertTookLockAndRelease(LockIsHeld.Yes, obj, tookLock);
        });

        scenario(delegate(object obj)
        {
            tookLock = false;
            Monitor.TryEnter(obj, ref tookLock);
            AssertTookLockAndRelease(Reverse(lockIsHeld), obj, tookLock);
        });

        scenario(delegate(object obj)
        {
            tookLock = false;
            Monitor.TryEnter(obj, 0, ref tookLock);
            AssertTookLockAndRelease(Reverse(lockIsHeld), obj, tookLock);
        });

        scenario(delegate(object obj)
        {
            tookLock = false;
            Monitor.TryEnter(obj, 10000, ref tookLock);
            AssertTookLockAndRelease(LockIsHeld.Maybe, obj, tookLock);
        });

        scenario(delegate(object obj)
        {
            tookLock = false;
            Monitor.TryEnter(obj, Timeout.Infinite, ref tookLock);
            AssertTookLockAndRelease(LockIsHeld.Yes, obj, tookLock);
        });

        scenario(delegate(object obj)
        {
            tookLock = false;
            Monitor.TryEnter(obj, TimeSpan.FromMilliseconds(0), ref tookLock);
            AssertTookLockAndRelease(Reverse(lockIsHeld), obj, tookLock);
        });

        scenario(delegate(object obj)
        {
            tookLock = false;
            Monitor.TryEnter(obj, TimeSpan.FromMilliseconds(10000), ref tookLock);
            AssertTookLockAndRelease(LockIsHeld.Maybe, obj, tookLock);
        });

        scenario(delegate(object obj)
        {
            tookLock = false;
            Monitor.TryEnter(obj, TimeSpan.FromMilliseconds(Timeout.Infinite), ref tookLock);
            AssertTookLockAndRelease(LockIsHeld.Yes, obj, tookLock);
        });

        if (lockIsHeld == LockIsHeld.No)
        {
            scenario(delegate(object obj)
            {
                Monitor.Enter(obj);
                Monitor.Enter(obj);
                AssertTookLockAndRelease(LockIsHeld.Yes, obj, true);
                AssertTookLockAndRelease(LockIsHeld.Yes, obj, true);
                AssertTookLockAndRelease(LockIsHeld.No, obj, false);
            });

            scenario(delegate(object obj)
            {
                Monitor.Enter(obj);
                tookLock = false;
                Monitor.Enter(obj, ref tookLock);
                AssertTookLockAndRelease(LockIsHeld.Yes, obj, tookLock);
                AssertTookLockAndRelease(LockIsHeld.Yes, obj, true);
                AssertTookLockAndRelease(LockIsHeld.No, obj, false);
            });

            scenario(delegate(object obj)
            {
                Monitor.Enter(obj);
                tookLock = false;
                Monitor.TryEnter(obj, ref tookLock);
                AssertTookLockAndRelease(LockIsHeld.Yes, obj, tookLock);
                AssertTookLockAndRelease(LockIsHeld.Yes, obj, true);
                AssertTookLockAndRelease(LockIsHeld.No, obj, false);
            });

            scenario(delegate(object obj)
            {
                Monitor.Enter(obj);
                for (int i = 0; i < 70; i++)
                {
                    Monitor.Enter(obj);
                }
                for (int i = 0; i < 70; i++)
                {
                    AssertTookLockAndRelease(LockIsHeld.Yes, obj, true);
                }
                AssertTookLockAndRelease(LockIsHeld.Yes, obj, true);
                AssertTookLockAndRelease(LockIsHeld.No, obj, false);
            });

            scenario(delegate(object obj)
            {
                Monitor.Enter(obj);
                for (int i = 0; i < 70; i++)
                {
                    tookLock = false;
                    Monitor.Enter(obj, ref tookLock);
                    Assert(tookLock);
                }
                for (int i = 0; i < 70; i++)
                {
                    AssertTookLockAndRelease(LockIsHeld.Yes, obj, true);
                }
                AssertTookLockAndRelease(LockIsHeld.Yes, obj, true);
                AssertTookLockAndRelease(LockIsHeld.No, obj, false);
            });

            scenario(delegate(object obj)
            {
                Monitor.Enter(obj);
                for (int i = 0; i < 70; i++)
                {
                    tookLock = false;
                    Monitor.TryEnter(obj, ref tookLock);
                    Assert(tookLock);
                }
                for (int i = 0; i < 70; i++)
                {
                    AssertTookLockAndRelease(LockIsHeld.Yes, obj, true);
                }
                AssertTookLockAndRelease(LockIsHeld.Yes, obj, true);
                AssertTookLockAndRelease(LockIsHeld.No, obj, false);
            });
        }
    }