//
        // Tries to unregister the callback. This method is thread-safe.
        //

        public bool Unregister()
        {
            StParker p = parker;

            if (p == null)
            {
                return(false);
            }

            parker = null;

            if (p.TryCancel())
            {
                p.Unpark(StParkStatus.WaitCancelled);
                return(true);
            }
            return(false);
        }
Exemplo n.º 2
0
        //
        // Signals a waitable and waits on another as an atomic
        // operation, activating the specified cancellers.
        //

        public static bool SignalAndWait(StWaitable tos, StWaitable tow, StCancelArgs cargs)
        {
            //
            // Create a parker to execute the WaitAny prologue on the
            // *tow* waitable.
            //

            StParker  pk   = new StParker();
            WaitBlock hint = null;
            int       sc   = 0;
            WaitBlock wb   = tow._WaitAnyPrologue(pk, StParkStatus.Success, ref hint, ref sc);

            //
            // Signal the *tos* waitable.
            //

            if (!tos._Release())
            {
                //
                // The signal operation failed. So, try to cancel the parker and,
                // if successful, cancel the acquire attempt; otherwise, wait until
                // the thread is unparked and, then, undo the acquire.
                //

                if (pk.TryCancel())
                {
                    tow._CancelAcquire(wb, hint);
                }
                else
                {
                    pk.Park();
                    tow._UndoAcquire();
                }

                //
                // Report the failure appropriately.
                //

                throw tos._SignalException;
            }

            //
            // Park the current thread, activating the specified cancellers
            // and spinning if appropriate.
            //

            int ws = pk.Park(sc, cargs);

            //
            // If we acquired, execute the WaitOne epilogue and return success.
            //

            if (ws == StParkStatus.Success)
            {
                tow._WaitEpilogue();
                return(true);
            }

            //
            // The acquire operation was cancelled; so, cancel the acquire
            // attempt and report the failure appropriately.
            //

            tow._CancelAcquire(wb, hint);
            StCancelArgs.ThrowIfException(ws);
            return(false);
        }
Exemplo n.º 3
0
        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);
        }