//
        // Spins until the specified condition is true.
        //

        internal static void SpinUntil(Func<bool> condition) {
            if (condition == null) {
                throw new ArgumentNullException("condition");
            }
            StSpinWait spinner = new StSpinWait();
            while (!condition()) {
                spinner.SpinOnce();
            }
        }
        //
        // Spins until the specified condition is true.
        //

        internal static void SpinUntil(Func <bool> condition)
        {
            if (condition == null)
            {
                throw new ArgumentNullException("condition");
            }
            StSpinWait spinner = new StSpinWait();

            while (!condition())
            {
                spinner.SpinOnce();
            }
        }
        //
        // Unregisters the registered wait.
        //

        public bool Unregister() {

	        //
	        // If the unregister is being called from the callback method,
	        // we just set the *onlyOnce* to TRUE and return.
	        //

	        if (cbtid == Thread.CurrentThread.ManagedThreadId) {
		        executeOnce = true;
		        return true;
	        }

	        //
	        // If the wait is registered, we try to unregister it, and return
	        // only after the wait is actually unregistered.
	        // If the wait was already unregistered or an unregister is taking
            // place, this method returns false.
	        //

            StSpinWait spinner = new StSpinWait();
            StParker pk = new StParker(0);
            StParker oldState;
            do {
		        if ((oldState = state) == INACTIVE) {
			        return false;
		        }
                if (oldState == ACTIVE) {
			        if (Interlocked.CompareExchange<StParker>(ref state, pk, ACTIVE) == ACTIVE) {
				        break;
			        }
                } else if (!(oldState is SentinelParker)) {
                    return false;
                }
		        spinner.SpinOnce();
	        } while (true);

	        //
	        // Try to cancel the wait's callback parker. If we succeed, call
	        // the unpark with status disposed. Otherwise, a callback is taking
	        // place and we must synchronize with its end.
	        //

	        if (cbparker.TryCancel()) {
                cbparker.Unpark(StParkStatus.WaitCancelled);
	        } else {
                pk.Park(BUSY_SPINS, StCancelArgs.None);
	        }

	        //
	        // Set the registered wait object to inactive and return success.
	        //

	        state = INACTIVE;
	        return true;
        }
        //
        // Unregisters the registered take.
        //

        public bool Unregister()
        {
            //
            // If the unregister is being called from the callback method,
            // we just set the *onlyOnce* to *true* and return.
            //

            if (cbtid == Thread.CurrentThread.ManagedThreadId)
            {
                executeOnce = true;
                return(true);
            }

            //
            // If the take is registered, we try to unregister it, and return
            // only after the wait is actually unregistered.
            // If the take was already unregistered or an unregister is taking
            // place, this method returns false.
            //

            StSpinWait spinner = new StSpinWait();
            StParker   pk      = new StParker(0);
            StParker   oldState;

            do
            {
                if ((oldState = state) == INACTIVE)
                {
                    return(false);
                }
                if (oldState == ACTIVE)
                {
                    if (Interlocked.CompareExchange <StParker>(ref state, pk, ACTIVE) == ACTIVE)
                    {
                        break;
                    }
                }
                else if (!(oldState is SentinelParker))
                {
                    return(false);
                }
                spinner.SpinOnce();
            } while (true);

            //
            // Try to cancel the callback parker. If we succeed, call the unpark
            // with status cancelled. Otherwise, a callback is taking place and
            // we must wait until its completion.
            //

            if (cbparker.TryCancel())
            {
                cbparker.Unpark(StParkStatus.TakeCancelled);
            }
            else
            {
                pk.Park(BUSY_SPINS, StCancelArgs.None);
            }

            //
            // Set the registered take object to inactive and return success.
            //

            state = INACTIVE;
            return(true);
        }
        //
        // Cancels the timer.
        //

        public bool Cancel() {

	        //
	        // If the timer is being cancelled from the user callback function,
	        // set the period to zero and return success. The timer will be
	        // cancelled on return from the callback function.
	        //

	        if (cbtid == Thread.CurrentThread.ManagedThreadId) {
		        period = 0;
		        return true;
	        }

	        //
	        // If the timer is active we must try to cancel the timer
	        // and return only after the timer is actually cancelled.
        	// if the timer is already inactive or a cancel or a set is taking
	        // place, this function returns FALSE. 
	        //

            StSpinWait spinner = new StSpinWait();
            StParker pk = new StParker(0);
            StParker oldState;
            do {
		        if ((oldState = state) == INACTIVE) {
			        return false;
		        }
                if (oldState == ACTIVE) {
			        if (Interlocked.CompareExchange<StParker>(ref state, pk, ACTIVE) == ACTIVE) {
				        break;
			        }
		        } if (!(oldState is SentinelParker)) {
			        return false;
		        }
		        spinner.SpinOnce();
	        } while (true);

	        //
	        // Try to cancel the timer's callback parker. If we can't
            // park the current thread until the timer callback finishes
            // execution.
	        //

	        if (cbparker.TryCancel()) {
		        cbparker.Unpark(StParkStatus.TimerCancelled);
	        } else {
                pk.Park(100, StCancelArgs.None);
            }

	        //
	        // Set the timer state to inactive and return success.
	        //

	        state = INACTIVE;
	        return true;
        }
        //
        // Sets the timer.
        //

        public bool Set(int dueTime, int period, WaitOrTimerCallback callback, object cbState) {

	        //
	        // If the timer is being set from the user callback function,
	        // we just save the new settings and return success.
	        //

	        if (cbtid == Thread.CurrentThread.ManagedThreadId) {
		        this.dueTime = dueTime;
		        this.period = period;
		        useDueTime = true;
		        this.callback = callback;
		        this.cbState = cbState;
		        return true;
	        }

	        //
	        // The timer is being set externally. So, we must first cancel the
	        // timer. If the timer is already being set or cancelled, we return
	        // failure.
	        //

            StSpinWait spinner = new StSpinWait();
            StParker pk = new StParker(0);
            StParker oldState;
	        do {
		        if ((oldState = state) == INACTIVE) {
			        if (Interlocked.CompareExchange<StParker>(ref state, SETTING,
                                                              INACTIVE) == INACTIVE) {
				        goto SetTimer;
			        }
		        } else if (oldState == ACTIVE) {
			        if (Interlocked.CompareExchange<StParker>(ref state, pk, ACTIVE) == ACTIVE) {
				        break;
			        }
		        } else if (!(oldState is SentinelParker)) {
			        return false;
		        }
		        spinner.SpinOnce();
	        } while (true);

	        //
	        // Try to cancel the timer's callback parker. If succeed,
            // call the unpark method; otherwise, the timer callback is
            // taking place, so we must synchronize with its end.
	        //

	        if (cbparker.TryCancel()) {
		        cbparker.Unpark(StParkStatus.TimerCancelled);
	        } else {
		        pk.Park(100, StCancelArgs.None);
	        }

	        //
	        // Here, we know that the timer is cancelled and no one else
	        // is trying to set or cancel the timer.
	        // So, set the timer state to *our busy state* and start it with
	        // the new settings.
	        //

            state = SETTING;

        SetTimer:

	        this.dueTime = dueTime;
	        this.period = period;
	        useDueTime = false;
	        this.callback = callback;
	        this.cbState = cbState;
            StNotificationEvent nev = tmrEvent as StNotificationEvent;
            if (nev != null) {
                nev.Reset();
            } else {
                ((StSynchronizationEvent)tmrEvent).Reset();
            }

	        //
	        // Initialize the timer's parker, set the timer state to ACTIVE
            // and enable the unpark callback.
	        //

            cbparker.Reset();
            state = ACTIVE;
            int ws = cbparker.EnableCallback(dueTime, timer);
            if (ws != StParkStatus.Pending) {
		
		        //
		        // If the timer already fired or cancelled, call the unpark
		        // callback inline.
		        //

		        TimerCallback(ws);
	        }
	        return true;
        }
Beispiel #7
0
        //
        // Cancels the timer.
        //

        public bool Cancel()
        {
            //
            // If the timer is being cancelled from the user callback function,
            // set the period to zero and return success. The timer will be
            // cancelled on return from the callback function.
            //

            if (cbtid == Thread.CurrentThread.ManagedThreadId)
            {
                period = 0;
                return(true);
            }

            //
            // If the timer is active we must try to cancel the timer
            // and return only after the timer is actually cancelled.
            // if the timer is already inactive or a cancel or a set is taking
            // place, this function returns FALSE.
            //

            StSpinWait spinner = new StSpinWait();
            StParker   pk      = new StParker(0);
            StParker   oldState;

            do
            {
                if ((oldState = state) == INACTIVE)
                {
                    return(false);
                }
                if (oldState == ACTIVE)
                {
                    if (Interlocked.CompareExchange <StParker>(ref state, pk, ACTIVE) == ACTIVE)
                    {
                        break;
                    }
                }
                if (!(oldState is SentinelParker))
                {
                    return(false);
                }
                spinner.SpinOnce();
            } while (true);

            //
            // Try to cancel the timer's callback parker. If we can't
            // park the current thread until the timer callback finishes
            // execution.
            //

            if (cbparker.TryCancel())
            {
                cbparker.Unpark(StParkStatus.TimerCancelled);
            }
            else
            {
                pk.Park(100, StCancelArgs.None);
            }

            //
            // Set the timer state to inactive and return success.
            //

            state = INACTIVE;
            return(true);
        }
Beispiel #8
0
        //
        // Sets the timer.
        //

        public bool Set(int dueTime, int period, WaitOrTimerCallback callback, object cbState)
        {
            //
            // If the timer is being set from the user callback function,
            // we just save the new settings and return success.
            //

            if (cbtid == Thread.CurrentThread.ManagedThreadId)
            {
                this.dueTime  = dueTime;
                this.period   = period;
                useDueTime    = true;
                this.callback = callback;
                this.cbState  = cbState;
                return(true);
            }

            //
            // The timer is being set externally. So, we must first cancel the
            // timer. If the timer is already being set or cancelled, we return
            // failure.
            //

            StSpinWait spinner = new StSpinWait();
            StParker   pk      = new StParker(0);
            StParker   oldState;

            do
            {
                if ((oldState = state) == INACTIVE)
                {
                    if (Interlocked.CompareExchange <StParker>(ref state, SETTING,
                                                               INACTIVE) == INACTIVE)
                    {
                        goto SetTimer;
                    }
                }
                else if (oldState == ACTIVE)
                {
                    if (Interlocked.CompareExchange <StParker>(ref state, pk, ACTIVE) == ACTIVE)
                    {
                        break;
                    }
                }
                else if (!(oldState is SentinelParker))
                {
                    return(false);
                }
                spinner.SpinOnce();
            } while (true);

            //
            // Try to cancel the timer's callback parker. If succeed,
            // call the unpark method; otherwise, the timer callback is
            // taking place, so we must synchronize with its end.
            //

            if (cbparker.TryCancel())
            {
                cbparker.Unpark(StParkStatus.TimerCancelled);
            }
            else
            {
                pk.Park(100, StCancelArgs.None);
            }

            //
            // Here, we know that the timer is cancelled and no one else
            // is trying to set or cancel the timer.
            // So, set the timer state to *our busy state* and start it with
            // the new settings.
            //

            state = SETTING;

SetTimer:

            this.dueTime  = dueTime;
            this.period   = period;
            useDueTime    = false;
            this.callback = callback;
            this.cbState  = cbState;
            StNotificationEvent nev = tmrEvent as StNotificationEvent;

            if (nev != null)
            {
                nev.Reset();
            }
            else
            {
                ((StSynchronizationEvent)tmrEvent).Reset();
            }

            //
            // Initialize the timer's parker, set the timer state to ACTIVE
            // and enable the unpark callback.
            //

            cbparker.Reset();
            state = ACTIVE;
            int ws = cbparker.EnableCallback(dueTime, timer);

            if (ws != StParkStatus.Pending)
            {
                //
                // If the timer already fired or cancelled, call the unpark
                // callback inline.
                //

                TimerCallback(ws);
            }
            return(true);
        }