A
download LockHelper.cs
Language: C#
LOC: 200
Project Info
ncindy - NCindy is a .NET port of the Cind...work.(ncindy)
Server: Google
Type: svn
...indy\trunk\src\NCindy\Util\
   AbstractDisposable.cs
   AysncCallWrapper.cs
   Configuration.cs
   ElapsedTime.cs
   LangHelper.cs
   LockHelper.cs
   SocketFactory.cs
   ValueTypeWrapper.cs
   WinSock2Wrapper.cs

using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Runtime.InteropServices;

namespace NCindy.Util
{
    public static class LockHelper
    {
        public static ValueTypeWrapper<LockCookie> SafeAcquireWriterLock(ReaderWriterLock readerWriterlock,
            int timeout)
        {
            ValueTypeWrapper<LockCookie> lockCookie = ValueTypeWrapper<LockCookie>.Empty;

            if (readerWriterlock.IsReaderLockHeld && !readerWriterlock.IsWriterLockHeld)
            {
                lockCookie = new ValueTypeWrapper<LockCookie>(readerWriterlock.UpgradeToWriterLock(timeout));
            }
            else
            {
                readerWriterlock.AcquireWriterLock(timeout);
            }

            return lockCookie;
        }

        public static void SafeReleaseWriterLock(ReaderWriterLock readerWriterlock,
            ValueTypeWrapper<LockCookie> lockCookie)
        {
            if (!readerWriterlock.IsWriterLockHeld)
            {
                return;
            }
            if (ValueTypeWrapper<LockCookie>.Empty == lockCookie)
            {
                readerWriterlock.ReleaseWriterLock();
            }
            else
            {
                LockCookie cookie = lockCookie.Value;
                readerWriterlock.DowngradeFromWriterLock(ref cookie);
            }
        }
    }

    public static class InterlockedHelper
    {
        #region Interlocked Helpers
        public static Int32 And(ref Int32 target, Int32 with)
        {
            Int32 i, j = target;
            do
            {
                i = j;
                j = Interlocked.CompareExchange(ref target, i & with, i);
            } while (i != j);
            return j;
        }

        public static Int32 Or(ref Int32 target, Int32 with)
        {
            Int32 i, j = target;
            do
            {
                i = j;
                j = Interlocked.CompareExchange(ref target, i | with, i);
            } while (i != j);
            return j;
        }

        public static bool CompareAndExchange(ref Int32 value,
            Int32 ifThisEqualsToValue,
            Int32 thenExchangeValueWithThis)
        {
            return (Interlocked.CompareExchange(ref value, thenExchangeValueWithThis, ifThisEqualsToValue) == ifThisEqualsToValue);
        }

        public static bool CompareAndExchange(ref Int32 value,
            Int32 ifThisEqualsToValue,
            Int32 thenExchangeValueWithThis,
            out Int32 originalValue)
        {
            originalValue = Interlocked.CompareExchange(ref value,
                thenExchangeValueWithThis,
                ifThisEqualsToValue);
            return (originalValue == ifThisEqualsToValue);
        }
        #endregion

    }

    #region SpinWaitLock

    // NOTE: This is a value type so it works very efficiently when used as
    // a field in a class. Avoid boxing this or you will lose thread safety!
    public struct SpinWaitLock
    {
        private static readonly Boolean IsSingleCpuMachine =
            (Environment.ProcessorCount == 1);

        private const Int32 LockIsFree  = 0;
        private const Int32 LockIsOwned = 1;


        private Int32 lockState; // Defaults to 0=c_lsFree

        public void Enter()
        {
            Thread.BeginCriticalRegion();
            while (true)
            {
                // If resource available, set it to in-use and return
                if (Interlocked.Exchange(
                    ref lockState, LockIsOwned) == LockIsFree)
                {
                    return;
                }

                // Efficiently spin, until the resource looks like it might 
                // be free. NOTE: Just reading here (as compared to repeatedly 
                // calling Exchange) improves performance because writing 
                // forces all CPUs to update this value
                while (Thread.VolatileRead(ref lockState) == LockIsOwned)
                {
                    StallThread();
                }
            }
        }

        public void Exit()
        {
            // Mark the resource as available
            Interlocked.Exchange(ref lockState, LockIsFree);
            Thread.EndCriticalRegion();
        }

        
        private static void StallThread()
        {
            // On a single-CPU system, spinning does no good
            if (IsSingleCpuMachine)
            {
                SwitchToThread();
            }
            else
            {
                // Multi-CPU system might be hyper-threaded, let other thread run
                Thread.SpinWait(1);
            }
        }

        [DllImport("kernel32", ExactSpelling = true)]
        private static extern void SwitchToThread();
    }

    #endregion

    public sealed class LightLock : IDisposable
    {
        // Bit     0: 0=Lock is free, 1=Lock is owned
        // Bits 1-31: Number of waiters
        private const Int32 LockIsFree = 0x00000000;//h000
        private const Int32 LockIsOwned = 0x00000001;//h001
        private const Int32 WaitersCountBase = 0x00000002;//h010

        private Int32 lockState = LockIsFree;

        private readonly Semaphore waiterLock = new Semaphore(0, Int32.MaxValue);

        private bool isDisposed;

        public LightLock()
        {
            isDisposed = false;
        }

        public void Dispose()
        {
            CheckDisposed();
            try
            {
                waiterLock.Close();
            }
            finally
            {
                this.isDisposed = true;
            }
        }

        private void CheckDisposed()
        {
            if (this.isDisposed)
            {
                throw new ObjectDisposedException(null);
            }
        }

        public void Enter()
        {
            this.Enter(Timeout.Infinite);
        }

        public void Enter(int timeout)
        {
            CheckDisposed();
            Thread.BeginCriticalRegion();
            while (true)
            {
                // Turn on the "owned" bit
                Int32 ls = InterlockedHelper.Or(ref lockState, LockIsOwned);

                // If lock was free, this thread got it, return
                if ((ls & LockIsOwned) == LockIsFree)
                {
                    return;
                }

                // Another thread owned the lock, add 1 waiter
                if (InterlockedHelper.CompareAndExchange(ref lockState, ls, ls + WaitersCountBase))
                {
                    // If successfully added 1, wait for lock
                    waiterLock.WaitOne(timeout, false);
                }

                // We weren't able to add 1 waiter or waiter woke, attempt to get the lock
            }
        }

        public void Exit()
        {
            CheckDisposed();

            // Pre-condition:  Lock's state must be Owned
            // Post-condition: Lock's state must become Free (the lock is never passed)

            // Free the lock, Turn off the owned bit.
            Int32 ls = InterlockedHelper.And(ref lockState, ~LockIsOwned);
            if (ls == LockIsOwned)
            {
                // If no waiters, nothing to do, we can just return
            }
            else
            {
                // Possibly wake waiters
                // If lock is free, try to subtract 1 from the number of waiters
                ls &= ~LockIsOwned;
                if (InterlockedHelper.CompareAndExchange(ref lockState, ls & ~LockIsOwned, ls - WaitersCountBase))
                {
                    // We sucessfully subtracted 1, wake 1 waiter
                    waiterLock.Release(1);
                }
                else
                {
                    // Lock's state changed by other thread, other thread will deal with it
                }
            }
            Thread.EndCriticalRegion();

        }

    }
}

About Koders | Resources | Downloads | Support | Black Duck | Terms of Service | DMCA | Privacy Policy | Contact Us