private bool SlowEnter(StCancelArgs cargs)
        {
            int       lastTime      = cargs.Timeout != Timeout.Infinite ? Environment.TickCount : 0;
            bool      timeRemaining = true;
            WaitBlock wb            = EnqueueWaiter();

            do
            {
                if (TryEnter())
                {
                    Cleanup(wb);
                    return(true);
                }

                if (!timeRemaining)
                {
                    return(false);
                }

                int ws = wb.parker.Park(head.next == wb ? spinCount : 0, cargs);

                if (ws != StParkStatus.Success)
                {
                    StCancelArgs.ThrowIfException(ws);
                    return(false);
                }

                if (TryEnter())
                {
                    Cleanup(wb);
                    return(true);
                }

                //
                // We failed to acquire the lock so we must clear the current
                // thread as the candidate owner. After doing so we must recheck
                // the state of lock. If the wait timed out, we exit the loop
                // before parking again.
                //

                if ((timeRemaining = cargs.AdjustTimeout(ref lastTime)))
                {
                    wb.parker.Reset();
                }

                //
                // Avoid a release-followed-by-acquire hazard.
                //

                Interlocked.Exchange(ref wb.request, ACQUIRE);
            } while (true);
        }
        internal static bool WaitAllInternal(StWaitable[] ws, WaitHandle[] hs, StCancelArgs cargs)
        {
            if (ws == null)
            {
                throw new ArgumentNullException("ws");
            }

            int nevts;
            int len = ws.Length;

            StWaitable[] sws = new StWaitable[len];
            WaitHandle[] shs = null;

            int waitHint = SortAndCheckAllowAcquire(ws, sws, out nevts);

            if (waitHint < 0)
            {
                throw new ArgumentException("There are duplicate waitables", "ws");
            }

            if (hs != null)
            {
                shs = Sort(hs);
                if (shs == null)
                {
                    throw new ArgumentException("There are duplicate wait handles", "hs");
                }
            }

            if (waitHint != 0 && shs != null && !WaitHandle.WaitAll(shs, 0))
            {
                waitHint = 0;
            }

            //
            // Return success if all synchronizers are notification events and are set.
            //

            if (waitHint != 0 && nevts == 0)
            {
                return(true);
            }

            if (waitHint == 0 && cargs.Timeout == 0)
            {
                return(false);
            }

            //
            // If a timeout was specified, get the current time in order
            // to adjust the timeout value later, if we re-wait.
            //

            int lastTime = (cargs.Timeout != Timeout.Infinite) ? Environment.TickCount : 0;

            WaitBlock[] wbs   = null;
            WaitBlock[] hints = null;
            do
            {
                if (waitHint == 0)
                {
                    //
                    // Create the wait block arrays if this is the first time
                    // that we execute the acquire-all prologue.
                    //

                    if (wbs == null)
                    {
                        wbs   = new WaitBlock[len];
                        hints = new WaitBlock[len];
                    }

                    //
                    // Create a parker for cooperative release, specifying as many
                    // releasers as the number of waitables. The parker because is
                    // not reused because other threads may have references to it.
                    //

                    StParker pk = shs != null
                                ? new StParker(len, EventBasedParkSpotFactory.Current.
                                               Create(new WaitAllBehavior(shs)))
                                : new StParker(len);

                    int gsc = 1;
                    int sc  = 0;
                    for (int i = 0; i < len; i++)
                    {
                        if ((wbs[i] = sws[i]._WaitAllPrologue(pk, ref hints[i], ref sc)) == null)
                        {
                            if (pk.TryLock())
                            {
                                pk.UnparkSelf(StParkStatus.StateChange);
                            }
                        }
                        else if (gsc != 0)
                        {
                            if (sc == 0)
                            {
                                gsc = 0;
                            }
                            else if (sc > gsc)
                            {
                                gsc = sc;
                            }
                        }
                    }

                    int wst = pk.Park(gsc, cargs);

                    //
                    // If the wait was cancelled due to timeout, alert or interrupt,
                    // cancel the acquire attempt on all waitables where we actually
                    // inserted wait blocks.
                    //

                    if (wst != StParkStatus.StateChange)
                    {
                        for (int i = 0; i < len; i++)
                        {
                            WaitBlock wb = wbs[i];
                            if (wb != null)
                            {
                                sws[i]._CancelAcquire(wb, hints[i]);
                            }
                        }

                        StCancelArgs.ThrowIfException(wst);
                        return(false);
                    }
                }

                //
                // All waitables where we inserted wait blocks seem to allow
                // an immediate acquire operation; so, try to acquire all of
                // them that are not notification events.
                //

                int idx;
                for (idx = 0; idx < nevts; idx++)
                {
                    if (!sws[idx]._TryAcquire())
                    {
                        break;
                    }
                }

                //
                // If all synchronizers were acquired, return success.
                //

                if (idx == nevts)
                {
                    return(true);
                }

                //
                // We failed to acquire all waitables, so undo the acquires
                // that we did above.
                //

                while (--idx >= 0)
                {
                    sws[idx]._UndoAcquire();
                }

                if (shs != null)
                {
                    for (int i = 0; i < shs.Length; i++)
                    {
                        shs[i].UndoAcquire();
                    }
                }

                //
                // If a timeout was specified, adjust the timeout value
                // that will be used on the next wait.
                //

                if (!cargs.AdjustTimeout(ref lastTime))
                {
                    return(false);
                }

                waitHint = 0;
            } while (true);
        }
        public void Wait(StParker pk, StCancelArgs cargs) {
            bool interrupted = false;
            int lastTime = (cargs.Timeout != Timeout.Infinite) ? Environment.TickCount : 0;
            int ws;
            do {
                try {
                    ws = waitBehavior.Park(psevent, cargs.Timeout);
                    break;
                } catch (ThreadInterruptedException) {
                    if (cargs.Interruptible) {
                        ws = StParkStatus.Interrupted;
                        break;
                    }
                    interrupted = true;
                    cargs.AdjustTimeout(ref lastTime);
                }
            } while (true);

            //
            // If the wait was cancelled due to an internal canceller, try
            // to cancel the park operation. If we fail, wait unconditionally
            // until the park spot is signalled.
            //

            if (ws != StParkStatus.Success) {
                if (pk.TryCancel()) {
                    pk.UnparkSelf(waitBehavior.ParkerCancelled(ws));
                } else {
                    if (ws == StParkStatus.Interrupted) {
                        interrupted = true;
                    }

                    waitBehavior.ParkerNotCancelled(ws);

                    do {
                        try {
                            psevent.WaitOne();
                            break;
                        } catch (ThreadInterruptedException) {
                            interrupted = true;
                        }
                    } while (true);
                }
            }

            //
            // If we were interrupted but can't return the *interrupted*
            // wait status, reassert the interrupt on the current thread.
            //

            if (interrupted) {
                Thread.CurrentThread.Interrupt();
            }

            factory.Free(this);
        }
        public void Wait(StParker pk, StCancelArgs cargs)
        {
            bool interrupted = false;
            int  lastTime    = (cargs.Timeout != Timeout.Infinite) ? Environment.TickCount : 0;
            int  ws;

            do
            {
                try {
                    ws = waitBehavior.Park(psevent, cargs.Timeout);
                    break;
                } catch (ThreadInterruptedException) {
                    if (cargs.Interruptible)
                    {
                        ws = StParkStatus.Interrupted;
                        break;
                    }
                    interrupted = true;
                    cargs.AdjustTimeout(ref lastTime);
                }
            } while (true);

            //
            // If the wait was cancelled due to an internal canceller, try
            // to cancel the park operation. If we fail, wait unconditionally
            // until the park spot is signalled.
            //

            if (ws != StParkStatus.Success)
            {
                if (pk.TryCancel())
                {
                    pk.UnparkSelf(waitBehavior.ParkerCancelled(ws));
                }
                else
                {
                    if (ws == StParkStatus.Interrupted)
                    {
                        interrupted = true;
                    }

                    waitBehavior.ParkerNotCancelled(ws);

                    do
                    {
                        try {
                            psevent.WaitOne();
                            break;
                        } catch (ThreadInterruptedException) {
                            interrupted = true;
                        }
                    } while (true);
                }
            }

            //
            // If we were interrupted but can't return the *interrupted*
            // wait status, reassert the interrupt on the current thread.
            //

            if (interrupted)
            {
                Thread.CurrentThread.Interrupt();
            }

            factory.Free(this);
        }
        //
        // Tries to acquire a busy lock, activating the specified cancellers.
        //

        private bool SlowEnter(StCancelArgs cargs) {

	        //
	        // If a timeout was specified, get a time reference in order
            // to adjust the timeout value if the thread need to re-wait.
	        //

	        int lastTime = (cargs.Timeout != Timeout.Infinite) ? Environment.TickCount : 0;
            WaitBlock wb = null;
            do {
		        //
		        // First, try to acquire the lock spinning for the configured
                // number of cycles, but only if the wait queue is empty.
		        //
		    
                int sc = spinCount;
		        do {
			        if (state == FREE &&
                        Interlocked.CompareExchange(ref state, BUSY, FREE) == FREE) {
                        return true;
                    }
                    if (top != null || sc-- <= 0) {
                        break;
                    }
                    Platform.SpinWait(1);
                } while (true);

                //
		        // The lock is busy; so, create a wait block or reset the
                // one previously created and insert it in the wait queue.
		        //

                if (wb == null) {
                    wb = new WaitBlock(ACQUIRE);
                } else {
                    wb.parker.Reset();
                }
                do {
                    WaitBlock t;
                    wb.next = (t = top);
                    if (Interlocked.CompareExchange<WaitBlock>(ref top, wb, t) == t) {
                        break;
                    }
                } while (true);

                //
                // Since that the lock can become free after we inserted
                // the wait block, we must retry to acquire the lock, if it
                // seems free.
                //

                if (TryEnter()) {
                    return true;
                }

                //
                // Park the current thread, activating the specified cancellers.
                //

                int ws = wb.parker.Park(cargs);

                //
                // If the acquire attempt was cancelled; so, report the
                // failure appropriately.
                //

                if (ws != StParkStatus.Success) {
                    StCancelArgs.ThrowIfException(ws);
                    return false;
                }

                //
                // Before adjust the timeout value, try to acquire the lock.
                //

			    if (TryEnter()) {
                    return true;
                }
            
		        //
		        // If a timeout was specified, adjust its value taking into
                // account the elapsed time.
		        //

                if (!cargs.AdjustTimeout(ref lastTime)) {
                    return false;
                }
            } while (true);
        }
        private bool SlowEnter(StCancelArgs cargs) {
            int lastTime = cargs.Timeout != Timeout.Infinite ? Environment.TickCount : 0;
            bool timeRemaining = true;
            WaitBlock wb = EnqueueWaiter();

            do {
                if (TryEnter()) {
                    Cleanup(wb);
                    return true;
                }

                if (!timeRemaining) {
                    return false;
                }

                int ws = wb.parker.Park(head.next == wb ? spinCount : 0, cargs); 

                if (ws != StParkStatus.Success) {
                    StCancelArgs.ThrowIfException(ws);
                    return false;
                }

                if (TryEnter()) {
                    Cleanup(wb);
                    return true;
                }
                
                //
                // We failed to acquire the lock so we must clear the current 
                // thread as the candidate owner. After doing so we must recheck 
                // the state of lock. If the wait timed out, we exit the loop
                // before parking again.
                //

                if ((timeRemaining = cargs.AdjustTimeout(ref lastTime))) {
                    wb.parker.Reset();
                }

                //
                // Avoid a release-followed-by-acquire hazard.
                // 

                Interlocked.Exchange(ref wb.request, ACQUIRE);
            } while (true);
        }
        //
        // Tries to acquire a busy lock, activating the specified cancellers.
        //

        private bool SlowEnter(StCancelArgs cargs)
        {
            //
            // If a timeout was specified, get a time reference in order
            // to adjust the timeout value if the thread need to re-wait.
            //

            int       lastTime = (cargs.Timeout != Timeout.Infinite) ? Environment.TickCount : 0;
            WaitBlock wb       = null;

            do
            {
                //
                // First, try to acquire the lock spinning for the configured
                // number of cycles, but only if the wait queue is empty.
                //

                int sc = spinCount;
                do
                {
                    if (state == FREE &&
                        Interlocked.CompareExchange(ref state, BUSY, FREE) == FREE)
                    {
                        return(true);
                    }
                    if (top != null || sc-- <= 0)
                    {
                        break;
                    }
                    Platform.SpinWait(1);
                } while (true);

                //
                // The lock is busy; so, create a wait block or reset the
                // one previously created and insert it in the wait queue.
                //

                if (wb == null)
                {
                    wb = new WaitBlock(ACQUIRE);
                }
                else
                {
                    wb.parker.Reset();
                }
                do
                {
                    WaitBlock t;
                    wb.next = (t = top);
                    if (Interlocked.CompareExchange <WaitBlock>(ref top, wb, t) == t)
                    {
                        break;
                    }
                } while (true);

                //
                // Since that the lock can become free after we inserted
                // the wait block, we must retry to acquire the lock, if it
                // seems free.
                //

                if (TryEnter())
                {
                    return(true);
                }

                //
                // Park the current thread, activating the specified cancellers.
                //

                int ws = wb.parker.Park(cargs);

                //
                // If the acquire attempt was cancelled; so, report the
                // failure appropriately.
                //

                if (ws != StParkStatus.Success)
                {
                    StCancelArgs.ThrowIfException(ws);
                    return(false);
                }

                //
                // Before adjust the timeout value, try to acquire the lock.
                //

                if (TryEnter())
                {
                    return(true);
                }

                //
                // If a timeout was specified, adjust its value taking into
                // account the elapsed time.
                //

                if (!cargs.AdjustTimeout(ref lastTime))
                {
                    return(false);
                }
            } while (true);
        }
        internal static bool WaitAllInternal(StWaitable[] ws, WaitHandle[] hs, StCancelArgs cargs) {
            if (ws == null) {
                throw new ArgumentNullException("ws");
            }

            int nevts;
            int len = ws.Length;
            StWaitable[] sws = new StWaitable[len];
            WaitHandle[] shs = null;

            int waitHint = SortAndCheckAllowAcquire(ws, sws, out nevts);
            
            if (waitHint < 0) {
                throw new ArgumentException("There are duplicate waitables", "ws");
            }

            if (hs != null) { 
                shs = Sort(hs);
                if (shs == null) {
                    throw new ArgumentException("There are duplicate wait handles", "hs");
                }
            }

            if (waitHint != 0 && shs != null && !WaitHandle.WaitAll(shs, 0)) {
                waitHint = 0;
            }

            //
            // Return success if all synchronizers are notification events and are set.
            //

            if (waitHint != 0 && nevts == 0) {
                return true;
            }

            if (waitHint == 0 && cargs.Timeout == 0) {
                return false;
            }

            //
            // If a timeout was specified, get the current time in order
            // to adjust the timeout value later, if we re-wait.
            //

            int lastTime = (cargs.Timeout != Timeout.Infinite) ? Environment.TickCount : 0;
            WaitBlock[] wbs = null;
            WaitBlock[] hints = null;
            do {
                if (waitHint == 0) {

                    //
                    // Create the wait block arrays if this is the first time
                    // that we execute the acquire-all prologue.
                    //
                    
                    if (wbs == null) {
                        wbs = new WaitBlock[len];
                        hints = new WaitBlock[len];
                    }

                    //
                    // Create a parker for cooperative release, specifying as many
                    // releasers as the number of waitables. The parker because is
                    // not reused because other threads may have references to it.
                    //

                    StParker pk = shs != null 
                                ? new StParker(len, EventBasedParkSpotFactory.Current.
                                                    Create(new WaitAllBehavior(shs)))
                                : new StParker(len);

                    int gsc = 1;
                    int sc = 0;
                    for (int i = 0; i < len; i++) {
                        if ((wbs[i] = sws[i]._WaitAllPrologue(pk, ref hints[i], ref sc)) == null) {
                            if (pk.TryLock()) {
                                pk.UnparkSelf(StParkStatus.StateChange);
                            }
                        } else if (gsc != 0) {
                            if (sc == 0) {
                                gsc = 0;
                            } else if (sc > gsc) {
                                gsc = sc;
                            }
                        }
                    }
                    
                    int wst = pk.Park(gsc, cargs);

                    //
                    // If the wait was cancelled due to timeout, alert or interrupt,
                    // cancel the acquire attempt on all waitables where we actually
                    // inserted wait blocks.
                    //

                    if (wst != StParkStatus.StateChange) {
                        for (int i = 0; i < len; i++) {
                            WaitBlock wb = wbs[i];
                            if (wb != null) {
                                sws[i]._CancelAcquire(wb, hints[i]);
                            }
                        }
                        
                        StCancelArgs.ThrowIfException(wst);
                        return false;
                    }
                }
            
                //
                // All waitables where we inserted wait blocks seem to allow 
                // an immediate acquire operation; so, try to acquire all of
                // them that are not notification events.
                //

                int idx;
                for (idx = 0; idx < nevts; idx++) {
                    if (!sws[idx]._TryAcquire()) {
                        break;
                    }
                }

                //
                // If all synchronizers were acquired, return success.
                //

                if (idx == nevts) {
                    return true;
                }

                //
                // We failed to acquire all waitables, so undo the acquires
                // that we did above.
                //

                while (--idx >= 0) {
                    sws[idx]._UndoAcquire();
                }

                if (shs != null) {
                    for (int i = 0; i < shs.Length; i++) {
                        shs[i].UndoAcquire();
                    }
                }

                //
                // If a timeout was specified, adjust the timeout value
                // that will be used on the next wait.
                //

                if (!cargs.AdjustTimeout(ref lastTime)) {
                    return false;
                }

                waitHint = 0;
            } while (true);
        }