Exit() private method

private Exit ( object obj ) : void
obj object
return void
Ejemplo n.º 1
0
 /// <summary>
 /// Releases resources used by the synchronized block.
 /// </summary>
 protected virtual void Dispose(bool disposing)
 {
     if (disposing && this.IsLockTaken)
     {
         SystemMonitor.Exit(this.SyncObject);
     }
 }
Ejemplo n.º 2
0
        public void TestComplexMonitor()
        {
            this.Test(async() =>
            {
                object syncObject = new object();
                bool waiting      = false;
                List <string> log = new List <string>();
                Task t1           = Task.Run(() =>
                {
                    Monitor.Enter(syncObject);
                    log.Add("waiting");
                    waiting = true;
                    Monitor.Wait(syncObject);
                    log.Add("received pulse");
                    Monitor.Exit(syncObject);
                });

                Task t2 = Task.Run(async() =>
                {
                    while (!waiting)
                    {
                        await Task.Delay(1);
                    }

                    Monitor.Enter(syncObject);
                    Monitor.Pulse(syncObject);
                    log.Add("pulsed");
                    Monitor.Exit(syncObject);
                });

                await Task.WhenAll(t1, t2);

                string expected = "waiting, pulsed, received pulse";
                string actual   = string.Join(", ", log);
                Specification.Assert(expected == actual, "ControlledMonitor out of order, '{0}' instead of '{1}'", actual, expected);
            },
                      this.GetConfiguration());
        }
Ejemplo n.º 3
0
        /// <summary>Gets an enumerable of the tasks currently scheduled on this scheduler.</summary>
        /// <returns>An enumerable of the tasks currently scheduled.</returns>
        protected sealed override IEnumerable <Task> GetScheduledTasks()
        {
            bool lockTaken = false;

            try
            {
                Monitor.TryEnter(_tasks, ref lockTaken);
                if (lockTaken)
                {
                    return(_tasks);
                }
                else
                {
                    throw new NotSupportedException();
                }
            }
            finally
            {
                if (lockTaken)
                {
                    Monitor.Exit(_tasks);
                }
            }
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Blocks the current thread until it can enter the <see cref="SemaphoreSlim"/>,
        /// using a 32-bit signed integer to measure the time interval,
        /// while observing a <see cref="T:System.Threading.CancellationToken"/>.
        /// </summary>
        /// <param name="millisecondsTimeout">The number of milliseconds to wait, or <see cref="Timeout.Infinite"/>(-1) to
        /// wait indefinitely.</param>
        /// <param name="cancellationToken">The <see cref="T:System.Threading.CancellationToken"/> to observe.</param>
        /// <returns>true if the current thread successfully entered the <see cref="SemaphoreSlim"/>; otherwise, false.</returns>
        /// <exception cref="ArgumentOutOfRangeException"><paramref name="millisecondsTimeout"/> is a negative number other than -1,
        /// which represents an infinite time-out.</exception>
        /// <exception cref="System.OperationCanceledException"><paramref name="cancellationToken"/> was canceled.</exception>
        public bool Wait(int millisecondsTimeout, CancellationToken cancellationToken)
        {
            CheckDispose();

            // Validate input
            if (millisecondsTimeout < -1)
            {
                throw new ArgumentOutOfRangeException(
                          "totalMilliSeconds", millisecondsTimeout, SR.SemaphoreSlim_Wait_TimeoutWrong);
            }

            cancellationToken.ThrowIfCancellationRequested();

            uint startTime = 0;

            if (millisecondsTimeout != Timeout.Infinite && millisecondsTimeout > 0)
            {
                startTime = TimeoutHelper.GetTime();
            }

            bool        waitSuccessful = false;
            Task <bool> asyncWaitTask  = null;
            bool        lockTaken      = false;

            //Register for cancellation outside of the main lock.
            //NOTE: Register/deregister inside the lock can deadlock as different lock acquisition orders could
            //      occur for (1)this.m_lockObj and (2)cts.internalLock
            CancellationTokenRegistration cancellationTokenRegistration = cancellationToken.InternalRegisterWithoutEC(s_cancellationTokenCanceledEventHandler, this);

            try
            {
                // Perf: first spin wait for the count to be positive, but only up to the first planned yield.
                //       This additional amount of spinwaiting in addition
                //       to Monitor.Enter()’s spinwaiting has shown measurable perf gains in test scenarios.
                //
                SpinWait spin = new SpinWait();
                while (m_currentCount == 0 && !spin.NextSpinWillYield)
                {
                    spin.SpinOnce();
                }
                // entering the lock and incrementing waiters must not suffer a thread-abort, else we cannot
                // clean up m_waitCount correctly, which may lead to deadlock due to non-woken waiters.
                try { }
                finally
                {
                    Monitor.Enter(m_lock, ref lockTaken);
                    if (lockTaken)
                    {
                        m_waitCount++;
                    }
                }

                // If there are any async waiters, for fairness we'll get in line behind
                // then by translating our synchronous wait into an asynchronous one that we
                // then block on (once we've released the lock).
                if (m_asyncHead != null)
                {
                    Contract.Assert(m_asyncTail != null, "tail should not be null if head isn't");
                    asyncWaitTask = WaitAsync(millisecondsTimeout, cancellationToken);
                }
                // There are no async waiters, so we can proceed with normal synchronous waiting.
                else
                {
                    // If the count > 0 we are good to move on.
                    // If not, then wait if we were given allowed some wait duration

                    OperationCanceledException oce = null;

                    if (m_currentCount == 0)
                    {
                        if (millisecondsTimeout == 0)
                        {
                            return(false);
                        }

                        // Prepare for the main wait...
                        // wait until the count become greater than zero or the timeout is expired
                        try
                        {
                            waitSuccessful = WaitUntilCountOrTimeout(millisecondsTimeout, startTime, cancellationToken);
                        }
                        catch (OperationCanceledException e) { oce = e; }
                    }

                    // Now try to acquire.  We prioritize acquisition over cancellation/timeout so that we don't
                    // lose any counts when there are asynchronous waiters in the mix.  Asynchronous waiters
                    // defer to synchronous waiters in priority, which means that if it's possible an asynchronous
                    // waiter didn't get released because a synchronous waiter was present, we need to ensure
                    // that synchronous waiter succeeds so that they have a chance to release.
                    Contract.Assert(!waitSuccessful || m_currentCount > 0,
                                    "If the wait was successful, there should be count available.");
                    if (m_currentCount > 0)
                    {
                        waitSuccessful = true;
                        m_currentCount--;
                    }
                    else if (oce != null)
                    {
                        throw oce;
                    }

                    // Exposing wait handle which is lazily initialized if needed
                    if (m_waitHandle != null && m_currentCount == 0)
                    {
                        m_waitHandle.Reset();
                    }
                }
            }
            finally
            {
                // Release the lock
                if (lockTaken)
                {
                    m_waitCount--;
                    Monitor.Exit(m_lock);
                }

                // Unregister the cancellation callback.
                cancellationTokenRegistration.Dispose();
            }

            // If we had to fall back to asynchronous waiting, block on it
            // here now that we've released the lock, and return its
            // result when available.  Otherwise, this was a synchronous
            // wait, and whether we successfully acquired the semaphore is
            // stored in waitSuccessful.

            return((asyncWaitTask != null) ? asyncWaitTask.GetAwaiter().GetResult() : waitSuccessful);
        }